declare namespace RPGMakerMV {
    interface TextState {
        index?: number;
        x?: number;
        y?: number;
        left?: number;
        text?: string;
        height?: number;
    }

    interface DataCommand {
        name: string;
        symbol: string;
        enabled: boolean;
        ext: number;
    }

    type NameInputLatin1 = [
        'A','B','C','D','E',  'a','b','c','d','e',
        'F','G','H','I','J',  'f','g','h','i','j',
        'K','L','M','N','O',  'k','l','m','n','o',
        'P','Q','R','S','T',  'p','q','r','s','t',
        'U','V','W','X','Y',  'u','v','w','x','y',
        'Z','[',']','^','_',  'z','{','}','|','~',
        '0','1','2','3','4',  '!','#','$','%','&',
        '5','6','7','8','9',  '(',')','*','+','-',
        '/','=','@','<','>',  ':',';',' ','Page','OK',
    ];
    type NameInputLatin2 = [
        'Á','É','Í','Ó','Ú',  'á','é','í','ó','ú',
        'À','È','Ì','Ò','Ù',  'à','è','ì','ò','ù',
        'Â','Ê','Î','Ô','Û',  'â','ê','î','ô','û',
        'Ä','Ë','Ï','Ö','Ü',  'ä','ë','ï','ö','ü',
        'Ā','Ē','Ī','Ō','Ū',  'ā','ē','ī','ō','ū',
        'Ã','Å','Æ','Ç','Ð',  'ã','å','æ','ç','ð',
        'Ñ','Õ','Ø','Š','Ŵ',  'ñ','õ','ø','š','ŵ',
        'Ý','Ŷ','Ÿ','Ž','Þ',  'ý','ÿ','ŷ','ž','þ',
        'Ĳ','Œ','ĳ','œ','ß',  '«','»',' ','Page','OK',
    ];
    type NameInputCyrillic = [
        'А','Б','В','Г','Д',  'а','б','в','г','д',
        'Е','Ё','Ж','З','И',  'е','ё','ж','з','и',
        'Й','К','Л','М','Н',  'й','к','л','м','н',
        'О','П','Р','С','Т',  'о','п','р','с','т',
        'У','Ф','Х','Ц','Ч',  'у','ф','х','ц','ч',
        'Ш','Щ','Ъ','Ы','Ь',  'ш','щ','ъ','ы','ь',
        'Э','Ю','Я','^','_',  'э','ю','я','%','&',
        '0','1','2','3','4',  '(',')','*','+','-',
        '5','6','7','8','9',  ':',';',' ','','OK',
    ];
    type NameInputHiragana = [
        'あ','い','う','え','お',  'が','ぎ','ぐ','げ','ご',
        'か','き','く','け','こ',  'ざ','じ','ず','ぜ','ぞ',
        'さ','し','す','せ','そ',  'だ','ぢ','づ','で','ど',
        'た','ち','つ','て','と',  'ば','び','ぶ','べ','ぼ',
        'な','に','ぬ','ね','の',  'ぱ','ぴ','ぷ','ぺ','ぽ',
        'は','ひ','ふ','へ','ほ',  'ぁ','ぃ','ぅ','ぇ','ぉ',
        'ま','み','む','め','も',  'っ','ゃ','ゅ','ょ','ゎ',
        'や','ゆ','よ','わ','ん',  'ー','～','・','＝','☆',
        'ら','り','る','れ','ろ',  'ゔ','を','　','カナ','決定',
    ];
    type NameInputKatakana = [
        'ア','イ','ウ','エ','オ',  'ガ','ギ','グ','ゲ','ゴ',
        'カ','キ','ク','ケ','コ',  'ザ','ジ','ズ','ゼ','ゾ',
        'サ','シ','ス','セ','ソ',  'ダ','ヂ','ヅ','デ','ド',
        'タ','チ','ツ','テ','ト',  'バ','ビ','ブ','ベ','ボ',
        'ナ','ニ','ヌ','ネ','ノ',  'パ','ピ','プ','ペ','ポ',
        'ハ','ヒ','フ','ヘ','ホ',  'ァ','ィ','ゥ','ェ','ォ',
        'マ','ミ','ム','メ','モ',  'ッ','ャ','ュ','ョ','ヮ',
        'ヤ','ユ','ヨ','ワ','ン',  'ー','～','・','＝','☆',
        'ラ','リ','ル','レ','ロ',  'ヴ','ヲ','　','英数','決定',
    ];
    type NameInputFullwidthLatin = [
        'Ａ','Ｂ','Ｃ','Ｄ','Ｅ',  'ａ','ｂ','ｃ','ｄ','ｅ',
        'Ｆ','Ｇ','Ｈ','Ｉ','Ｊ',  'ｆ','ｇ','ｈ','ｉ','ｊ',
        'Ｋ','Ｌ','Ｍ','Ｎ','Ｏ',  'ｋ','ｌ','ｍ','ｎ','ｏ',
        'Ｐ','Ｑ','Ｒ','Ｓ','Ｔ',  'ｐ','ｑ','ｒ','ｓ','ｔ',
        'Ｕ','Ｖ','Ｗ','Ｘ','Ｙ',  'ｕ','ｖ','ｗ','ｘ','ｙ',
        'Ｚ','［','］','＾','＿',  'ｚ','｛','｝','｜','～',
        '０','１','２','３','４',  '！','＃','＄','％','＆',
        '５','６','７','８','９',  '（','）','＊','＋','－',
        '／','＝','＠','＜','＞',  '：','；','　','かな','決定',
    ];
}

//=============================================================================
// rpg_windows.js v1.6.2
//=============================================================================

//-----------------------------------------------------------------------------
// Window_Base
//
// The superclass of all windows within the game.

 class Window_Base extends Window {
    constructor(x?: number, y?: number, width?: number, height?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, width?: number, height?: number): void {
        Window.prototype.initialize.call(this);
        this.loadWindowskin();
        this.move(x, y, width, height);
        this.updatePadding();
        this.updateBackOpacity();
        this.updateTone();
        this.createContents();
        this._opening = false;
        this._closing = false;
        this._dimmerSprite = null;
    };
    _opening: boolean;
    _closing: boolean;
    _dimmerSprite: Sprite;

    static _iconWidth: number = 32;
    static _iconHeight: number = 32;
    static _faceWidth: number = 144;
    static _faceHeight: number = 144;

    lineHeight(): number {
        return 36;
    };
    standardFontFace(): string {
        if ($gameSystem.isChinese()) {
            return 'SimHei, Heiti TC, sans-serif';
        } else if ($gameSystem.isKorean()) {
            return 'Dotum, AppleGothic, sans-serif';
        } else {
            return 'GameFont';
        }
    };
    standardFontSize(): number {
        return 28;
    };
    standardPadding(): number {
        return 18;
    };
    textPadding(): number {
        return 6;
    };
    standardBackOpacity(): number {
        return 192;
    };
    loadWindowskin(): void {
        this.windowskin = ImageManager.loadSystem('Window');
    };
    updatePadding(): void {
        this.padding = this.standardPadding();
    };
    updateBackOpacity(): void {
        this.backOpacity = this.standardBackOpacity();
    };
    contentsWidth(): number {
        return this.width - this.standardPadding() * 2;
    };
    contentsHeight(): number {
        return this.height - this.standardPadding() * 2;
    };
    fittingHeight(numLines: number): number {
        return numLines * this.lineHeight() + this.standardPadding() * 2;
    };
    updateTone(): void {
        var tone = $gameSystem.windowTone();
        this.setTone(tone[0], tone[1], tone[2]);
    };
    createContents(): void {
        this.contents = new Bitmap(this.contentsWidth(), this.contentsHeight());
        this.resetFontSettings();
    };
    resetFontSettings(): void {
        this.contents.fontFace = this.standardFontFace();
        this.contents.fontSize = this.standardFontSize();
        this.resetTextColor();
    };
    resetTextColor(): void {
        this.changeTextColor(this.normalColor());
    };
    update(): void {
        Window.prototype.update.call(this);
        this.updateTone();
        this.updateOpen();
        this.updateClose();
        this.updateBackgroundDimmer();
    };
    updateOpen(): void {
        if (this._opening) {
            this.openness += 32;
            if (this.isOpen()) {
                this._opening = false;
            }
        }
    };
    updateClose(): void {
        if (this._closing) {
            this.openness -= 32;
            if (this.isClosed()) {
                this._closing = false;
            }
        }
    };
    open(): void {
        if (!this.isOpen()) {
            this._opening = true;
        }
        this._closing = false;
    };
    close(): void {
        if (!this.isClosed()) {
            this._closing = true;
        }
        this._opening = false;
    };
    isOpening(): boolean {
        return this._opening;
    };
    isClosing(): boolean {
        return this._closing;
    };
    show(): void {
        this.visible = true;
    };
    hide(): void {
        this.visible = false;
    };
    activate(): void {
        this.active = true;
    };
    deactivate(): void {
        this.active = false;
    };
    textColor(n: number): string {
        var px = 96 + (n % 8) * 12 + 6;
        var py = 144 + Math.floor(n / 8) * 12 + 6;
        return this.windowskin.getPixel(px, py);
    };
    normalColor(): string {
        return this.textColor(0);
    };
    systemColor(): string {
        return this.textColor(16);
    };
    crisisColor(): string {
        return this.textColor(17);
    };
    deathColor(): string {
        return this.textColor(18);
    };
    gaugeBackColor(): string {
        return this.textColor(19);
    };
    hpGaugeColor1(): string {
        return this.textColor(20);
    };
    hpGaugeColor2(): string {
        return this.textColor(21);
    };
    mpGaugeColor1(): string {
        return this.textColor(22);
    };
    mpGaugeColor2(): string {
        return this.textColor(23);
    };
    mpCostColor(): string {
        return this.textColor(23);
    };
    powerUpColor(): string {
        return this.textColor(24);
    };
    powerDownColor(): string {
        return this.textColor(25);
    };
    tpGaugeColor1(): string {
        return this.textColor(28);
    };
    tpGaugeColor2(): string {
        return this.textColor(29);
    };
    tpCostColor(): string {
        return this.textColor(29);
    };
    pendingColor(): string {
        return this.windowskin.getPixel(120, 120);
    };
    translucentOpacity(): number {
        return 160;
    };
    changeTextColor(color: string): void {
        this.contents.textColor = color;
    };
    changePaintOpacity(enabled: boolean|any): void {
        this.contents.paintOpacity = enabled ? 255 : this.translucentOpacity();
    };
    drawText(text: string|any, x: number, y: number, maxWidth?: number, align?: string|any): void {
        this.contents.drawText(text, x, y, maxWidth, this.lineHeight(), align);
    };
    textWidth(text: string): number {
        return this.contents.measureTextWidth(text);
    };
    drawTextEx(text: string, x: number, y: number, z?: any): number {
        if (text) {
            var textState:any = { index: 0, x: x, y: y, left: x };
            textState.text = this.convertEscapeCharacters(text);
            textState.height = this.calcTextHeight(textState, false);
            this.resetFontSettings();
            while (textState.index < textState.text.length) {
                this.processCharacter(textState);
            }
            return textState.x - x;
        } else {
            return 0;
        }
    };
    convertEscapeCharacters(text: string): string {
        let me = this;
        text = text.replace(/\\/g, '\x1b');
        text = text.replace(/\x1b\x1b/g, '\\');
        text = text.replace(/\x1bV\[(\d+)\]/gi, function() {
            return $gameVariables.value(parseInt(arguments[1]));
        }.bind(this));
        text = text.replace(/\x1bV\[(\d+)\]/gi, function() {
            return $gameVariables.value(parseInt(arguments[1]));
        }.bind(this));
        text = text.replace(/\x1bN\[(\d+)\]/gi, function() {
            return me.actorName(parseInt(arguments[1]));
        }.bind(this));
        text = text.replace(/\x1bP\[(\d+)\]/gi, function() {
            return me.partyMemberName(parseInt(arguments[1]));
        }.bind(this));
        text = text.replace(/\x1bG/gi, TextManager.currencyUnit);
        return text;
    };
    actorName(n: number): string {
        var actor = n >= 1 ? $gameActors.actor(n) : null;
        return actor ? actor.name() : '';
    };
    partyMemberName(n: number): string {
        var actor = n >= 1 ? $gameParty.members()[n - 1] : null;
        return actor ? actor.name() : '';
    };
    processCharacter(textState: RPGMakerMV.TextState): void {
        switch (textState.text[textState.index]) {
        case '\n':
            this.processNewLine(textState);
            break;
        case '\f':
            this.processNewPage(textState);
            break;
        case '\x1b':
            this.processEscapeCharacter(this.obtainEscapeCode(textState), textState);
            break;
        default:
            this.processNormalCharacter(textState);
            break;
        }
    };
    processNormalCharacter(textState: RPGMakerMV.TextState): void {
        var c = textState.text[textState.index++];
        var w = this.textWidth(c);
        this.contents.drawText(c, textState.x, textState.y, w * 2, textState.height);
        textState.x += w;
    };
    processNewLine(textState: RPGMakerMV.TextState): void {
        textState.x = textState.left;
        textState.y += textState.height;
        textState.height = this.calcTextHeight(textState, false);
        textState.index++;
    };
    processNewPage(textState: RPGMakerMV.TextState): void {
        textState.index++;
    };
    obtainEscapeCode(textState: RPGMakerMV.TextState): string {
        textState.index++;
        var regExp = /^[\$\.\|\^!><\{\}\\]|^[A-Z]+/i;
        var arr = regExp.exec(textState.text.slice(textState.index));
        if (arr) {
            textState.index += arr[0].length;
            return arr[0].toUpperCase();
        } else {
            return '';
        }
    };
    obtainEscapeParam(textState: RPGMakerMV.TextState): string|any {
        var arr = /^\[\d+\]/.exec(textState.text.slice(textState.index));
        if (arr) {
            textState.index += arr[0].length;
            return parseInt(arr[0].slice(1));
        } else {
            return '';
        }
    };
    processEscapeCharacter(code: string, textState: RPGMakerMV.TextState|any): void {
        switch (code) {
        case 'C':
            this.changeTextColor(this.textColor(this.obtainEscapeParam(textState)));
            break;
        case 'I':
            this.processDrawIcon(this.obtainEscapeParam(textState), textState);
            break;
        case '{':
            this.makeFontBigger();
            break;
        case '}':
            this.makeFontSmaller();
            break;
        }
    };
    processDrawIcon(iconIndex: number, textState: RPGMakerMV.TextState): void {
        this.drawIcon(iconIndex, textState.x + 2, textState.y + 2);
        textState.x += Window_Base._iconWidth + 4;
    };
    makeFontBigger(): void {
        if (this.contents.fontSize <= 96) {
            this.contents.fontSize += 12;
        }
    };
    makeFontSmaller(): void {
        if (this.contents.fontSize >= 24) {
            this.contents.fontSize -= 12;
        }
    };
    calcTextHeight(textState: RPGMakerMV.TextState, all: boolean): number {
        var lastFontSize = this.contents.fontSize;
        var textHeight = 0;
        var lines = textState.text.slice(textState.index).split('\n');
        var maxLines = all ? lines.length : 1;
    
        for (var i = 0; i < maxLines; i++) {
            var maxFontSize = this.contents.fontSize;
            var regExp = /\x1b[\{\}]/g;
            for (;;) {
                var array = regExp.exec(lines[i]);
                if (array) {
                    if (array[0] === '\x1b{') {
                        this.makeFontBigger();
                    }
                    if (array[0] === '\x1b}') {
                        this.makeFontSmaller();
                    }
                    if (maxFontSize < this.contents.fontSize) {
                        maxFontSize = this.contents.fontSize;
                    }
                } else {
                    break;
                }
            }
            textHeight += maxFontSize + 8;
        }
    
        this.contents.fontSize = lastFontSize;
        return textHeight;
    };
    drawIcon(iconIndex: number, x: number, y: number): void {
        var bitmap = ImageManager.loadSystem('IconSet');
        var pw = Window_Base._iconWidth;
        var ph = Window_Base._iconHeight;
        var sx = iconIndex % 16 * pw;
        var sy = Math.floor(iconIndex / 16) * ph;
        this.contents.blt(bitmap, sx, sy, pw, ph, x, y);
    };
    drawFace(faceName: string, faceIndex: number, x: number, y: number, width?: number, height?: number): void {
        width = width || Window_Base._faceWidth;
        height = height || Window_Base._faceHeight;
        var bitmap = ImageManager.loadFace(faceName);
        var pw = Window_Base._faceWidth;
        var ph = Window_Base._faceHeight;
        var sw = Math.min(width, pw);
        var sh = Math.min(height, ph);
        var dx = Math.floor(x + Math.max(width - pw, 0) / 2);
        var dy = Math.floor(y + Math.max(height - ph, 0) / 2);
        var sx = faceIndex % 4 * pw + (pw - sw) / 2;
        var sy = Math.floor(faceIndex / 4) * ph + (ph - sh) / 2;
        this.contents.blt(bitmap, sx, sy, sw, sh, dx, dy);
    };
    drawCharacter(characterName: string, characterIndex: number, x: number, y: number): void {
        var bitmap = ImageManager.loadCharacter(characterName);
        var big = ImageManager.isBigCharacter(characterName);
        var pw = bitmap.width / (big ? 3 : 12);
        var ph = bitmap.height / (big ? 4 : 8);
        var n = characterIndex;
        var sx = (n % 4 * 3 + 1) * pw;
        var sy = (Math.floor(n / 4) * 4) * ph;
        this.contents.blt(bitmap, sx, sy, pw, ph, x - pw / 2, y - ph);
    };
    drawGauge(x: number, y: number, width: number, rate: number, color1: string, color2: string): void {
        var fillW = Math.floor(width * rate);
        var gaugeY = y + this.lineHeight() - 8;
        this.contents.fillRect(x, gaugeY, width, 6, this.gaugeBackColor());
        this.contents.gradientFillRect(x, gaugeY, fillW, 6, color1, color2);
    };
    hpColor(actor: Game_Battler): string {
        if (actor.isDead()) {
            return this.deathColor();
        } else if (actor.isDying()) {
            return this.crisisColor();
        } else {
            return this.normalColor();
        }
    };
    mpColor(actor: Game_Battler): string {
        return this.normalColor();
    };
    tpColor(actor: Game_Battler): string {
        return this.normalColor();
    };
    drawActorCharacter(actor: Game_Actor, x: number, y: number): void {
        this.drawCharacter(actor.characterName(), actor.characterIndex(), x, y);
    };
    drawActorFace(actor: Game_Actor, x: number, y: number, width?: number, height?: number): void {
        this.drawFace(actor.faceName(), actor.faceIndex(), x, y, width, height);
    };
    drawActorName(actor: Game_Actor, x: number, y: number, width?: number): void {
        width = width || 168;
        this.changeTextColor(this.hpColor(actor));
        this.drawText(actor.name(), x, y, width);
    };
    drawActorClass(actor: Game_Actor, x: number, y: number, width?: number): void {
        width = width || 168;
        this.resetTextColor();
        this.drawText(actor.currentClass().name, x, y, width);
    };
    drawActorNickname(actor: Game_Actor, x: number, y: number, width?: number): void {
        width = width || 270;
        this.resetTextColor();
        this.drawText(actor.nickname(), x, y, width);
    };
    drawActorLevel(actor: Game_Actor|any, x: number, y: number): void {
        this.changeTextColor(this.systemColor());
        this.drawText(TextManager.levelA, x, y, 48);
        this.resetTextColor();
        this.drawText(actor.level, x + 84, y, 36, 'right');
    };
    drawActorIcons(actor: Game_Actor, x: number, y: number, width?: number): void {
        width = width || 144;
        var icons = actor.allIcons().slice(0, Math.floor(width / Window_Base._iconWidth));
        for (var i = 0; i < icons.length; i++) {
            this.drawIcon(icons[i], x + Window_Base._iconWidth * i, y + 2);
        }
    };
    drawCurrentAndMax(current: number|any, max: number|any, x: number, y: number, width: number, color1: string, color2: string): void {
        var labelWidth = this.textWidth('HP');
        var valueWidth = this.textWidth('0000');
        var slashWidth = this.textWidth('/');
        var x1 = x + width - valueWidth;
        var x2 = x1 - slashWidth;
        var x3 = x2 - valueWidth;
        if (x3 >= x + labelWidth) {
            this.changeTextColor(color1);
            this.drawText(current, x3, y, valueWidth, 'right');
            this.changeTextColor(color2);
            this.drawText('/', x2, y, slashWidth, 'right');
            this.drawText(max, x1, y, valueWidth, 'right');
        } else {
            this.changeTextColor(color1);
            this.drawText(current, x1, y, valueWidth, 'right');
        }
    };
    drawActorHp(actor: Game_Actor, x: number, y: number, width?: number): void {
        width = width || 186;
        var color1 = this.hpGaugeColor1();
        var color2 = this.hpGaugeColor2();
        this.drawGauge(x, y, width, actor.hpRate(), color1, color2);
        this.changeTextColor(this.systemColor());
        this.drawText(TextManager.hpA, x, y, 44);
        this.drawCurrentAndMax(actor.hp, actor.mhp, x, y, width,
                               this.hpColor(actor), this.normalColor());
    };
    drawActorMp(actor: Game_Actor, x: number, y: number, width?: number): void {
        width = width || 186;
        var color1 = this.mpGaugeColor1();
        var color2 = this.mpGaugeColor2();
        this.drawGauge(x, y, width, actor.mpRate(), color1, color2);
        this.changeTextColor(this.systemColor());
        this.drawText(TextManager.mpA, x, y, 44);
        this.drawCurrentAndMax(actor.mp, actor.mmp, x, y, width,
                               this.mpColor(actor), this.normalColor());
    };
    drawActorTp(actor: Game_Actor|any, x: number, y: number, width?: number): void {
        width = width || 96;
        var color1 = this.tpGaugeColor1();
        var color2 = this.tpGaugeColor2();
        this.drawGauge(x, y, width, actor.tpRate(), color1, color2);
        this.changeTextColor(this.systemColor());
        this.drawText(TextManager.tpA, x, y, 44);
        this.changeTextColor(this.tpColor(actor));
        this.drawText(actor.tp, x + width - 64, y, 64, 'right');
    };
    drawActorSimpleStatus(actor: Game_Actor, x: number, y: number, width: number): void {
        var lineHeight = this.lineHeight();
        var x2 = x + 180;
        var width2 = Math.min(200, width - 180 - this.textPadding());
        this.drawActorName(actor, x, y);
        this.drawActorLevel(actor, x, y + lineHeight * 1);
        this.drawActorIcons(actor, x, y + lineHeight * 2);
        this.drawActorClass(actor, x2, y);
        this.drawActorHp(actor, x2, y + lineHeight * 1, width2);
        this.drawActorMp(actor, x2, y + lineHeight * 2, width2);
    };
    drawItemName(item: RPGMakerMV.DataAnyItem | RPGMakerMV.DataSkill, x: number, y: number, width?: number): void {
        width = width || 312;
        if (item) {
            var iconBoxWidth = Window_Base._iconWidth + 4;
            this.resetTextColor();
            this.drawIcon(item.iconIndex, x + 2, y + 2);
            this.drawText(item.name, x + iconBoxWidth, y, width - iconBoxWidth);
        }
    };
    drawCurrencyValue(value: number|any, unit: string, x: number, y: number, width: number): void {
        var unitWidth = Math.min(80, this.textWidth(unit));
        this.resetTextColor();
        this.drawText(value, x, y, width - unitWidth - 6, 'right');
        this.changeTextColor(this.systemColor());
        this.drawText(unit, x + width - unitWidth, y, unitWidth, 'right');
    };
    paramchangeTextColor(change: number): string {
        if (change > 0) {
            return this.powerUpColor();
        } else if (change < 0) {
            return this.powerDownColor();
        } else {
            return this.normalColor();
        }
    };
    setBackgroundType(type: number): void {
        if (type === 0) {
            this.opacity = 255;
        } else {
            this.opacity = 0;
        }
        if (type === 1) {
            this.showBackgroundDimmer();
        } else {
            this.hideBackgroundDimmer();
        }
    };
    showBackgroundDimmer(): void {
        if (!this._dimmerSprite) {
            this._dimmerSprite = new Sprite();
            this._dimmerSprite.bitmap = new Bitmap(0, 0);
            this.addChildToBack(this._dimmerSprite);
        }
        var bitmap = this._dimmerSprite.bitmap;
        if (bitmap.width !== this.width || bitmap.height !== this.height) {
            this.refreshDimmerBitmap();
        }
        this._dimmerSprite.visible = true;
        this.updateBackgroundDimmer();
    };
    hideBackgroundDimmer(): void {
        if (this._dimmerSprite) {
            this._dimmerSprite.visible = false;
        }
    };
    updateBackgroundDimmer(): void {
        if (this._dimmerSprite) {
            this._dimmerSprite.opacity = this.openness;
        }
    };
    refreshDimmerBitmap(): void {
        if (this._dimmerSprite) {
            var bitmap = this._dimmerSprite.bitmap;
            var w = this.width;
            var h = this.height;
            var m = this.padding;
            var c1 = this.dimColor1();
            var c2 = this.dimColor2();
            bitmap.resize(w, h);
            bitmap.gradientFillRect(0, 0, w, m, c2, c1, true);
            bitmap.fillRect(0, m, w, h - m * 2, c1);
            bitmap.gradientFillRect(0, h - m, w, m, c1, c2, true);
            this._dimmerSprite.setFrame(0, 0, w, h);
        }
    };
    dimColor1(): string {
        return 'rgba(0, 0, 0, 0.6)';
    };
    dimColor2(): string {
        return 'rgba(0, 0, 0, 0)';
    };
    canvasToLocalX(x: number): number {
        var node:any = this;
        while (node) {
            x -= node.x;
            node = node.parent;
        }
        return x;
    };
    canvasToLocalY(y: number): number {
        var node:any = this;
        while (node) {
            y -= node.y;
            node = node.parent;
        }
        return y;
    };
    reserveFaceImages(): void {
        $gameParty.members().forEach(function(actor) {
            ImageManager.reserveFace(actor.faceName());
        }, this);
    };
}

//-----------------------------------------------------------------------------
// Window_Selectable
//
// The window class with cursor movement and scroll functions.

 class Window_Selectable extends Window_Base {
    constructor(x?: number, y?: number, width?: number, height?: number) {
        super();
        this.initialize.apply(this, arguments);
    }
     
    initialize(x?: number, y?: number, width?: number, height?: number): void {
        Window_Base.prototype.initialize.call(this, x, y, width, height);
        this._index = -1;
        this._cursorFixed = false;
        this._cursorAll = false;
        this._stayCount = 0;
        this._helpWindow = null;
        this._handlers = {};
        this._touching = false;
        this._scrollX = 0;
        this._scrollY = 0;
        this.deactivate();
    };

    _index: number;
    _cursorFixed: boolean;
    _cursorAll: boolean;
    _stayCount: number;
    _helpWindow: Window_Help;
    _handlers: { [key: string]: Function };
    _touching: boolean;
    _scrollX: number;
    _scrollY: number;

    index(): number {
        return this._index;
    };
    cursorFixed(): boolean {
        return this._cursorFixed;
    };
    setCursorFixed(cursorFixed: boolean): void {
        this._cursorFixed = cursorFixed;
    };
    
    cursorAll(): boolean {
        return this._cursorAll;
    };
    setCursorAll(cursorAll: boolean): void {
        this._cursorAll = cursorAll;
    };
    maxCols(): number {
        return 1;
    };
    maxItems(): number {
        return 0;
    };
    spacing(): number {
        return 12;
    };
    itemWidth(): number {
        return Math.floor((this.width - this.padding * 2 +
                           this.spacing()) / this.maxCols() - this.spacing());
    };
    itemHeight(): number {
        return this.lineHeight();
    };
    maxRows(): number {
        return Math.max(Math.ceil(this.maxItems() / this.maxCols()), 1);
    };
    activate(): void {
        Window_Base.prototype.activate.call(this);
        this.reselect();
    };
    deactivate(): void {
        Window_Base.prototype.deactivate.call(this);
        this.reselect();
    };
    select(index: number): void {
        this._index = index;
        this._stayCount = 0;
        this.ensureCursorVisible();
        this.updateCursor();
        this.callUpdateHelp();
    };
    deselect(): void {
        this.select(-1);
    };
    reselect(): void {
        this.select(this._index);
    };
    row(): number {
        return Math.floor(this.index() / this.maxCols());
    };
    topRow(): number {
        return Math.floor(this._scrollY / this.itemHeight());
    };
    maxTopRow(): number {
        return Math.max(0, this.maxRows() - this.maxPageRows());
    };
    setTopRow(row: number): void {
        var scrollY = row.clamp(0, this.maxTopRow()) * this.itemHeight();
        if (this._scrollY !== scrollY) {
            this._scrollY = scrollY;
            this.refresh();
            this.updateCursor();
        }
    };
    resetScroll(): void {
        this.setTopRow(0);
    };
    maxPageRows(): number {
        var pageHeight = this.height - this.padding * 2;
        return Math.floor(pageHeight / this.itemHeight());
    };
    maxPageItems(): number {
        return this.maxPageRows() * this.maxCols();
    };
    isHorizontal(): boolean {
        return this.maxPageRows() === 1;
    };
    bottomRow(): number {
        return Math.max(0, this.topRow() + this.maxPageRows() - 1);
    };
    setBottomRow(row: number): void {
        this.setTopRow(row - (this.maxPageRows() - 1));
    };
    topIndex(): number{
        return this.topRow() * this.maxCols();
    };
    itemRect(index: number): Rectangle{
        var rect = new Rectangle();
        var maxCols = this.maxCols();
        rect.width = this.itemWidth();
        rect.height = this.itemHeight();
        rect.x = index % maxCols * (rect.width + this.spacing()) - this._scrollX;
        rect.y = Math.floor(index / maxCols) * rect.height - this._scrollY;
        return rect;
    };
    itemRectForText(index: number): Rectangle{
        var rect = this.itemRect(index);
        rect.x += this.textPadding();
        rect.width -= this.textPadding() * 2;
        return rect;
    };
    setHelpWindow(helpWindow: Window_Help): void{
        this._helpWindow = helpWindow;
        this.callUpdateHelp();
    };
    showHelpWindow(): void{
        if (this._helpWindow) {
            this._helpWindow.show();
        }
    };
    hideHelpWindow(): void{
        if (this._helpWindow) {
            this._helpWindow.hide();
        }
    };
    setHandler(symbol: string, method: Function): void{
        this._handlers[symbol] = method;
    };
    isHandled(symbol: string): boolean {
        return !!this._handlers[symbol];
    };
    callHandler(symbol: string): void {
        if (this.isHandled(symbol)) {
            this._handlers[symbol]();
        }
    };
    isOpenAndActive(): boolean {
        return this.isOpen() && this.active;
    };
    isCursorMovable(): boolean {
        return (this.isOpenAndActive() && !this._cursorFixed &&
                !this._cursorAll && this.maxItems() > 0);
    };
    cursorDown(wrap?: boolean): void {
        var index = this.index();
        var maxItems = this.maxItems();
        var maxCols = this.maxCols();
        if (index < maxItems - maxCols || (wrap && maxCols === 1)) {
            this.select((index + maxCols) % maxItems);
        }
    };
    cursorUp(wrap?: boolean): void {
        var index = this.index();
        var maxItems = this.maxItems();
        var maxCols = this.maxCols();
        if (index >= maxCols || (wrap && maxCols === 1)) {
            this.select((index - maxCols + maxItems) % maxItems);
        }
    };
    cursorRight(wrap: boolean): void {
        var index = this.index();
        var maxItems = this.maxItems();
        var maxCols = this.maxCols();
        if (maxCols >= 2 && (index < maxItems - 1 || (wrap && this.isHorizontal()))) {
            this.select((index + 1) % maxItems);
        }
    };
    cursorLeft(wrap: boolean): void {
        var index = this.index();
        var maxItems = this.maxItems();
        var maxCols = this.maxCols();
        if (maxCols >= 2 && (index > 0 || (wrap && this.isHorizontal()))) {
            this.select((index - 1 + maxItems) % maxItems);
        }
    };
    cursorPagedown(): void {
        var index = this.index();
        var maxItems = this.maxItems();
        if (this.topRow() + this.maxPageRows() < this.maxRows()) {
            this.setTopRow(this.topRow() + this.maxPageRows());
            this.select(Math.min(index + this.maxPageItems(), maxItems - 1));
        }
    };
    cursorPageup(): void {
        var index = this.index();
        if (this.topRow() > 0) {
            this.setTopRow(this.topRow() - this.maxPageRows());
            this.select(Math.max(index - this.maxPageItems(), 0));
        }
    };
    scrollDown(): void {
        if (this.topRow() + 1 < this.maxRows()) {
            this.setTopRow(this.topRow() + 1);
        }
    };
    scrollUp(): void {
        if (this.topRow() > 0) {
            this.setTopRow(this.topRow() - 1);
        }
    };
    update(): void {
        Window_Base.prototype.update.call(this);
        this.updateArrows();
        this.processCursorMove();
        this.processHandling();
        this.processWheel();
        this.processTouch();
        this._stayCount++;
    };
    updateArrows(): void {
        var topRow = this.topRow();
        var maxTopRow = this.maxTopRow();
        this.downArrowVisible = maxTopRow > 0 && topRow < maxTopRow;
        this.upArrowVisible = topRow > 0;
    };
    processCursorMove(): void {
        if (this.isCursorMovable()) {
            var lastIndex = this.index();
            if (Input.isRepeated('down')) {
                this.cursorDown(Input.isTriggered('down'));
            }
            if (Input.isRepeated('up')) {
                this.cursorUp(Input.isTriggered('up'));
            }
            if (Input.isRepeated('right')) {
                this.cursorRight(Input.isTriggered('right'));
            }
            if (Input.isRepeated('left')) {
                this.cursorLeft(Input.isTriggered('left'));
            }
            if (!this.isHandled('pagedown') && Input.isTriggered('pagedown')) {
                this.cursorPagedown();
            }
            if (!this.isHandled('pageup') && Input.isTriggered('pageup')) {
                this.cursorPageup();
            }
            if (this.index() !== lastIndex) {
                SoundManager.playCursor();
            }
        }
    };
    processHandling(): void {
        if (this.isOpenAndActive()) {
            if (this.isOkEnabled() && this.isOkTriggered()) {
                this.processOk();
            } else if (this.isCancelEnabled() && this.isCancelTriggered()) {
                this.processCancel();
            } else if (this.isHandled('pagedown') && Input.isTriggered('pagedown')) {
                this.processPagedown();
            } else if (this.isHandled('pageup') && Input.isTriggered('pageup')) {
                this.processPageup();
            }
        }
    };
    processWheel(): void {
        if (this.isOpenAndActive()) {
            var threshold = 20;
            if (TouchInput.wheelY >= threshold) {
                this.scrollDown();
            }
            if (TouchInput.wheelY <= -threshold) {
                this.scrollUp();
            }
        }
    };
    processTouch(): void {
        if (this.isOpenAndActive()) {
            if (TouchInput.isTriggered() && this.isTouchedInsideFrame()) {
                this._touching = true;
                this.onTouch(true);
            } else if (TouchInput.isCancelled()) {
                if (this.isCancelEnabled()) {
                    this.processCancel();
                }
            }
            if (this._touching) {
                if (TouchInput.isPressed()) {
                    this.onTouch(false);
                } else {
                    this._touching = false;
                }
            }
        } else {
            this._touching = false;
        }
    };
    isTouchedInsideFrame(): boolean {
        var x = this.canvasToLocalX(TouchInput.x);
        var y = this.canvasToLocalY(TouchInput.y);
        return x >= 0 && y >= 0 && x < this.width && y < this.height;
    };
    onTouch(triggered: boolean): void {
        var lastIndex = this.index();
        var x = this.canvasToLocalX(TouchInput.x);
        var y = this.canvasToLocalY(TouchInput.y);
        var hitIndex = this.hitTest(x, y);
        if (hitIndex >= 0) {
            if (hitIndex === this.index()) {
                if (triggered && this.isTouchOkEnabled()) {
                    this.processOk();
                }
            } else if (this.isCursorMovable()) {
                this.select(hitIndex);
            }
        } else if (this._stayCount >= 10) {
            if (y < this.padding) {
                this.cursorUp();
            } else if (y >= this.height - this.padding) {
                this.cursorDown();
            }
        }
        if (this.index() !== lastIndex) {
            SoundManager.playCursor();
        }
    };
    hitTest(x: number, y: number): number {
        if (this.isContentsArea(x, y)) {
            var cx = x - this.padding;
            var cy = y - this.padding;
            var topIndex = this.topIndex();
            for (var i = 0; i < this.maxPageItems(); i++) {
                var index = topIndex + i;
                if (index < this.maxItems()) {
                    var rect = this.itemRect(index);
                    var right = rect.x + rect.width;
                    var bottom = rect.y + rect.height;
                    if (cx >= rect.x && cy >= rect.y && cx < right && cy < bottom) {
                        return index;
                    }
                }
            }
        }
        return -1;
    };
    isContentsArea(x: number, y: number): boolean {
        var left = this.padding;
        var top = this.padding;
        var right = this.width - this.padding;
        var bottom = this.height - this.padding;
        return (x >= left && y >= top && x < right && y < bottom);
    };
    isTouchOkEnabled(): boolean {
        return this.isOkEnabled();
    };
    isOkEnabled(): boolean {
        return this.isHandled('ok');
    };
    isCancelEnabled(): boolean {
        return this.isHandled('cancel');
    };
    isOkTriggered(): boolean {
        return Input.isRepeated('ok');
    };
    isCancelTriggered(): boolean {
        return Input.isRepeated('cancel');
    };
    processOk(): void {
        if (this.isCurrentItemEnabled()) {
            this.playOkSound();
            this.updateInputData();
            this.deactivate();
            this.callOkHandler();
        } else {
            this.playBuzzerSound();
        }
    };
    playOkSound(): void {
        SoundManager.playOk();
    };
    playBuzzerSound(): void {
        SoundManager.playBuzzer();
    };
    callOkHandler(): void {
        this.callHandler('ok');
    };
    processCancel(): void {
        SoundManager.playCancel();
        this.updateInputData();
        this.deactivate();
        this.callCancelHandler();
    };
    callCancelHandler(): void {
        this.callHandler('cancel');
    };
    processPageup(): void {
        SoundManager.playCursor();
        this.updateInputData();
        this.deactivate();
        this.callHandler('pageup');
    };
    processPagedown(): void {
        SoundManager.playCursor();
        this.updateInputData();
        this.deactivate();
        this.callHandler('pagedown');
    };
    updateInputData(): void {
        Input.update();
        TouchInput.update();
    };
    updateCursor(): void {
        if (this._cursorAll) {
            var allRowsHeight = this.maxRows() * this.itemHeight();
            this.setCursorRect(0, 0, this.contents.width, allRowsHeight);
            this.setTopRow(0);
        } else if (this.isCursorVisible()) {
            var rect = this.itemRect(this.index());
            this.setCursorRect(rect.x, rect.y, rect.width, rect.height);
        } else {
            this.setCursorRect(0, 0, 0, 0);
        }
    };
    isCursorVisible(): boolean {
        var row = this.row();
        return row >= this.topRow() && row <= this.bottomRow();
    };
    ensureCursorVisible(): void {
        var row = this.row();
        if (row < this.topRow()) {
            this.setTopRow(row);
        } else if (row > this.bottomRow()) {
            this.setBottomRow(row);
        }
    };
    callUpdateHelp(): void {
        if (this.active && this._helpWindow) {
            this.updateHelp();
        }
    };
    updateHelp(): void {
        this._helpWindow.clear();
    };
    setHelpWindowItem(item: RPGMakerMV.DataAnyItem | RPGMakerMV.DataSkill): void {
        if (this._helpWindow) {
            this._helpWindow.setItem(item);
        }
    };
    isCurrentItemEnabled(): boolean {
        return true;
    };
    drawAllItems(): void {
        var topIndex = this.topIndex();
        for (var i = 0; i < this.maxPageItems(); i++) {
            var index = topIndex + i;
            if (index < this.maxItems()) {
                this.drawItem(index);
            }
        }
    };
    drawItem(index: number): void {
    };
    clearItem(index: number): void {
        var rect = this.itemRect(index);
        this.contents.clearRect(rect.x, rect.y, rect.width, rect.height);
    };
    redrawItem(index: number): void {
        if (index >= 0) {
            this.clearItem(index);
            this.drawItem(index);
        }
    };
    redrawCurrentItem(): void {
        this.redrawItem(this.index());
    };
    
    refresh(): void {
        if (this.contents) {
            this.contents.clear();
            this.drawAllItems();
        }
    };
}

//-----------------------------------------------------------------------------
// Window_Command
//
// The superclass of windows for selecting a command.

 class Window_Command extends Window_Selectable {
    constructor(x?: number, y?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number): void {
        this.clearCommandList();
        this.makeCommandList();
        var width = this.windowWidth();
        var height = this.windowHeight();
        Window_Selectable.prototype.initialize.call(this, x, y, width, height);
        this.refresh();
        this.select(0);
        this.activate();
    };

    windowWidth(): number {
        return 240;
    };
    windowHeight(): number {
        return this.fittingHeight(this.numVisibleRows());
    };
    numVisibleRows(): number {
        return Math.ceil(this.maxItems() / this.maxCols());
    };
    maxItems(): number {
        return this._list.length;
    };
    clearCommandList(): void {
        this._list = [];
    };
    _list: RPGMakerMV.DataCommand[];
    makeCommandList(): void {
    };
    addCommand(name: string, symbol: string, enabled?: boolean, ext?: number): void {
        if (enabled === undefined) {
            enabled = true;
        }
        if (ext === undefined) {
            ext = null;
        }
        this._list.push({ name: name, symbol: symbol, enabled: enabled, ext: ext});
    };
    commandName(index: number): string {
        return this._list[index].name;
    };
    commandSymbol(index: number): string {
        return this._list[index].symbol;
    };
    isCommandEnabled(index: number): boolean {
        return this._list[index].enabled;
    };
    currentData(): RPGMakerMV.DataCommand {
        return this.index() >= 0 ? this._list[this.index()] : null;
    };
    isCurrentItemEnabled(): boolean {
        return this.currentData() ? this.currentData().enabled : false;
    };
    currentSymbol(): string{
        return this.currentData() ? this.currentData().symbol : null;
    };
    currentExt(): number {
        return this.currentData() ? this.currentData().ext : null;
    };
    findSymbol(symbol: string): number {
        for (var i = 0; i < this._list.length; i++) {
            if (this._list[i].symbol === symbol) {
                return i;
            }
        }
        return -1;
    };
    selectSymbol(symbol: string): void {
        var index = this.findSymbol(symbol);
        if (index >= 0) {
            this.select(index);
        } else {
            this.select(0);
        }
    };
    findExt(ext: number): number {
        for (var i = 0; i < this._list.length; i++) {
            if (this._list[i].ext === ext) {
                return i;
            }
        }
        return -1;
    };
    selectExt(ext: number): void {
        var index = this.findExt(ext);
        if (index >= 0) {
            this.select(index);
        } else {
            this.select(0);
        }
    };
    drawItem(index: number): void {
        var rect = this.itemRectForText(index);
        var align = this.itemTextAlign();
        this.resetTextColor();
        this.changePaintOpacity(this.isCommandEnabled(index));
        this.drawText(this.commandName(index), rect.x, rect.y, rect.width, align);
    };
    itemTextAlign(): string {
        return 'left';
    };
    isOkEnabled(): boolean {
        return true;
    };
    callOkHandler(): void {
        var symbol = this.currentSymbol();
        if (this.isHandled(symbol)) {
            this.callHandler(symbol);
        } else if (this.isHandled('ok')) {
            Window_Selectable.prototype.callOkHandler.call(this);
        } else {
            this.activate();
        }
    };
    refresh(): void {
        this.clearCommandList();
        this.makeCommandList();
        this.createContents();
        Window_Selectable.prototype.refresh.call(this);
    };
}

//-----------------------------------------------------------------------------
// Window_HorzCommand
//
// The command window for the horizontal selection format.

 class Window_HorzCommand extends Window_Command {
    constructor(x?: number, y?: number) {
        super();
        this.initialize.apply(this, arguments);
    }

    initialize(x?: number, y?: number): void{
        Window_Command.prototype.initialize.call(this, x, y);
    };
    numVisibleRows(): number {
        return 1;
    };
    maxCols(): number {
        return 4;
    };
    itemTextAlign(): string {
        return 'center';
    };
}

//-----------------------------------------------------------------------------
// Window_Help
//
// The window for displaying the description of the selected item.

 class Window_Help extends Window_Base {
    constructor(numLines?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(numLines?: number): void {
        var width = Graphics.boxWidth;
        var height = this.fittingHeight(numLines || 2);
        Window_Base.prototype.initialize.call(this, 0, 0, width, height);
        this._text = '';
    };
    _text: string;
    setText(text: string): void {
        if (this._text !== text) {
            this._text = text;
            this.refresh();
        }
    };
    clear(): void {
        this.setText('');
    };
    setItem(item: RPGMakerMV.DataAnyItem | RPGMakerMV.DataSkill): void {
        this.setText(item ? item.description : '');
    };
    refresh(): void {
        this.contents.clear();
        this.drawTextEx(this._text, this.textPadding(), 0);
    };
}

//-----------------------------------------------------------------------------
// Window_Gold
//
// The window for displaying the party's gold.

 class Window_Gold extends Window_Base {
    constructor(x?: number, y?: number) {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number): void {
        var width = this.windowWidth();
        var height = this.windowHeight();
        Window_Base.prototype.initialize.call(this, x, y, width, height);
        this.refresh();
    };
    windowWidth(): number {
        return 240;
    };
    windowHeight(): number {
        return this.fittingHeight(1);
    };
    refresh(): void {
        var x = this.textPadding();
        var width = this.contents.width - this.textPadding() * 2;
        this.contents.clear();
        this.drawCurrencyValue(this.value(), this.currencyUnit(), x, 0, width);
    };
    value(): number {
        return $gameParty.gold();
    };
    currencyUnit(): string {
        return TextManager.currencyUnit;
    };
    open(): void {
        this.refresh();
        Window_Base.prototype.open.call(this);
    };
}

//-----------------------------------------------------------------------------
// Window_MenuCommand
//
// The window for selecting a command on the menu screen.

 class Window_MenuCommand extends Window_Command {
    constructor(x?: number, y?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number): void {
        Window_Command.prototype.initialize.call(this, x, y);
        this.selectLast();
    };

    static _lastCommandSymbol: string = null;
    static initCommandPosition(): void {
        this._lastCommandSymbol = null;
    };

    windowWidth(): number {
        return 240;
    };
    numVisibleRows(): number {
        return this.maxItems();
    };
    makeCommandList(): void {
        this.addMainCommands();
        this.addFormationCommand();
        this.addOriginalCommands();
        this.addOptionsCommand();
        this.addSaveCommand();
        this.addGameEndCommand();
    };
    addMainCommands(): void {
        var enabled = this.areMainCommandsEnabled();
        if (this.needsCommand('item')) {
            this.addCommand(TextManager.item, 'item', enabled);
        }
        if (this.needsCommand('skill')) {
            this.addCommand(TextManager.skill, 'skill', enabled);
        }
        if (this.needsCommand('equip')) {
            this.addCommand(TextManager.equip, 'equip', enabled);
        }
        if (this.needsCommand('status')) {
            this.addCommand(TextManager.status, 'status', enabled);
        }
    };
    addFormationCommand(): void {
        if (this.needsCommand('formation')) {
            var enabled = this.isFormationEnabled();
            this.addCommand(TextManager.formation, 'formation', enabled);
        }
    };
    addOriginalCommands(): void {
    };
    addOptionsCommand(): void {
        if (this.needsCommand('options')) {
            var enabled = this.isOptionsEnabled();
            this.addCommand(TextManager.options, 'options', enabled);
        }
    };
    addSaveCommand(): void {
        if (this.needsCommand('save')) {
            var enabled = this.isSaveEnabled();
            this.addCommand(TextManager.save, 'save', enabled);
        }
    };
    addGameEndCommand(): void {
        var enabled = this.isGameEndEnabled();
        this.addCommand(TextManager.gameEnd, 'gameEnd', enabled);
    };
    needsCommand(name: string): boolean {
        var flags = $dataSystem.menuCommands;
        if (flags) {
            switch (name) {
            case 'item':
                return flags[0];
            case 'skill':
                return flags[1];
            case 'equip':
                return flags[2];
            case 'status':
                return flags[3];
            case 'formation':
                return flags[4];
            case 'save':
                return flags[5];
            }
        }
        return true;
    };
    areMainCommandsEnabled(): boolean {
        return $gameParty.exists();
    };
    isFormationEnabled(): boolean {
        return $gameParty.size() >= 2 && $gameSystem.isFormationEnabled();
    };
    isOptionsEnabled(): boolean {
        return true;
    };
    isSaveEnabled(): boolean {
        return !DataManager.isEventTest() && $gameSystem.isSaveEnabled();
    };
    isGameEndEnabled(): boolean {
        return true;
    };
    processOk(): void {
        Window_MenuCommand._lastCommandSymbol = this.currentSymbol();
        Window_Command.prototype.processOk.call(this);
    };
    selectLast(): void {
        this.selectSymbol(Window_MenuCommand._lastCommandSymbol);
    };
}

//-----------------------------------------------------------------------------
// Window_MenuStatus
//
// The window for displaying party member status on the menu screen.

 class Window_MenuStatus extends Window_Selectable {
    constructor(x?: number, y?: number) {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number): void{
        var width = this.windowWidth();
        var height = this.windowHeight();
        Window_Selectable.prototype.initialize.call(this, x, y, width, height);
        this._formationMode = false;
        this._pendingIndex = -1;
        this.refresh();
    };

    _formationMode: boolean;
    _pendingIndex: number;

    windowWidth(): number{
        return Graphics.boxWidth - 240;
    };
    windowHeight(): number {
        return Graphics.boxHeight;
    };
    maxItems(): number {
        return $gameParty.size();
    };
    itemHeight(): number {
        var clientHeight = this.height - this.padding * 2;
        return Math.floor(clientHeight / this.numVisibleRows());
    };
    numVisibleRows(): number {
        return 4;
    };
    loadImages(): void {
        $gameParty.members().forEach(function(actor) {
            ImageManager.reserveFace(actor.faceName());
        }, this);
    };
    drawItem(index: number): void {
        this.drawItemBackground(index);
        this.drawItemImage(index);
        this.drawItemStatus(index);
    };
    drawItemBackground(index: number): void {
        if (index === this._pendingIndex) {
            var rect = this.itemRect(index);
            var color = this.pendingColor();
            this.changePaintOpacity(false);
            this.contents.fillRect(rect.x, rect.y, rect.width, rect.height, color);
            this.changePaintOpacity(true);
        }
    };
    drawItemImage(index: number): void {
        var actor = $gameParty.members()[index];
        var rect = this.itemRect(index);
        this.changePaintOpacity(actor.isBattleMember());
        this.drawActorFace(actor, rect.x + 1, rect.y + 1, Window_Base._faceWidth, Window_Base._faceHeight);
        this.changePaintOpacity(true);
    };
    drawItemStatus(index: number): void {
        var actor = $gameParty.members()[index];
        var rect = this.itemRect(index);
        var x = rect.x + 162;
        var y = rect.y + rect.height / 2 - this.lineHeight() * 1.5;
        var width = rect.width - x - this.textPadding();
        this.drawActorSimpleStatus(actor, x, y, width);
    };
    processOk(): void {
        Window_Selectable.prototype.processOk.call(this);
        $gameParty.setMenuActor($gameParty.members()[this.index()]);
    };
    isCurrentItemEnabled(): boolean {
        if (this._formationMode) {
            var actor = $gameParty.members()[this.index()];
            return actor && actor.isFormationChangeOk();
        } else {
            return true;
        }
    };
    selectLast(): void {
        this.select($gameParty.menuActor().index() || 0);
    };
    formationMode(): boolean {
        return this._formationMode;
    };
    setFormationMode(formationMode: boolean): void {
        this._formationMode = formationMode;
    };
    pendingIndex(): number {
        return this._pendingIndex;
    };
    setPendingIndex(index: number): void {
        var lastPendingIndex = this._pendingIndex;
        this._pendingIndex = index;
        this.redrawItem(this._pendingIndex);
        this.redrawItem(lastPendingIndex);
    };
}

//-----------------------------------------------------------------------------
// Window_MenuActor
//
// The window for selecting a target actor on the item and skill screens.

 class Window_MenuActor extends Window_MenuStatus {
    constructor(){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(): void {
        Window_MenuStatus.prototype.initialize.call(this, 0, 0);
        this.hide();
    };
    processOk(): void {
        if (!this.cursorAll()) {
            $gameParty.setTargetActor($gameParty.members()[this.index()]);
        }
        this.callOkHandler();
    };
    selectLast(): void {
        this.select($gameParty.targetActor().index() || 0);
    };
    selectForItem(item: RPGMakerMV.DataAnyItem | RPGMakerMV.DataSkill|any): void {
        var actor = $gameParty.menuActor();
        var action = new Game_Action(actor);
        action.setItemObject(item);
        this.setCursorFixed(false);
        this.setCursorAll(false);
        if (action.isForUser()) {
            if (DataManager.isSkill(item)) {
                this.setCursorFixed(true);
                this.select(actor.index());
            } else {
                this.selectLast();
            }
        } else if (action.isForAll()) {
            this.setCursorAll(true);
            this.select(0);
        } else {
            this.selectLast();
        }
    };
}

//-----------------------------------------------------------------------------
// Window_ItemCategory
//
// The window for selecting a category of items on the item and shop screens.

 class Window_ItemCategory extends Window_HorzCommand {
    constructor(){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(): void {
        Window_HorzCommand.prototype.initialize.call(this, 0, 0);
    };
    _itemWindow: Window_ItemList;

    windowWidth(): number {
        return Graphics.boxWidth;
    };
    maxCols(): number {
        return 4;
    };    
    update(): void {
        Window_HorzCommand.prototype.update.call(this);
        if (this._itemWindow) {
            this._itemWindow.setCategory(this.currentSymbol());
        }
    };
    makeCommandList(): void {
        this.addCommand(TextManager.item,    'item');
        this.addCommand(TextManager.weapon,  'weapon');
        this.addCommand(TextManager.armor,   'armor');
        this.addCommand(TextManager.keyItem, 'keyItem');
    };
    setItemWindow(itemWindow: Window_ItemList): void {
        this._itemWindow = itemWindow;
    };
}

//-----------------------------------------------------------------------------
// Window_ItemList
//
// The window for selecting an item on the item screen.

 class Window_ItemList extends Window_Selectable {
    constructor(x?: number, y?: number, width?: number, height?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, width?: number, height?: number): void {
        Window_Selectable.prototype.initialize.call(this, x, y, width, height);
        this._category = 'none';
        this._data = [];
    };
    _category: string;
    _data: RPGMakerMV.DataAnyItem[];

    setCategory(category: string): void {
        if (this._category !== category) {
            this._category = category;
            this.refresh();
            this.resetScroll();
        }
    };
    maxCols(): number{
        return 2;
    };
    spacing(): number{
        return 48;
    };
    maxItems(): number {
        return this._data ? this._data.length : 1;
    };
    item(): RPGMakerMV.DataAnyItem {
        var index = this.index();
        return this._data && index >= 0 ? this._data[index] : null;
    };
    isCurrentItemEnabled(): boolean {
        return this.isEnabled(this.item());
    };
    includes(item: RPGMakerMV.DataAnyItem): boolean {
        switch (this._category) {
        case 'item':
            return DataManager.isItem(item) && item.itypeId === 1;
        case 'weapon':
            return DataManager.isWeapon(item);
        case 'armor':
            return DataManager.isArmor(item);
        case 'keyItem':
            return DataManager.isItem(item) && item.itypeId === 2;
        default:
            return false;
        }
    };
    needsNumber(): boolean {
        return true;
    };
    isEnabled(item: RPGMakerMV.DataAnyItem): boolean {
        return $gameParty.canUse(item);
    };
    makeItemList(): void {
        this._data = $gameParty.allItems().filter(item=> {
            return this.includes(item);
        }, this);
        if (this.includes(null)) {
            this._data.push(null);
        }
    };
    selectLast(): void {
        var index = this._data.indexOf($gameParty.lastItem());
        this.select(index >= 0 ? index : 0);
    };
    drawItem(index: number): void {
        var item = this._data[index];
        if (item) {
            var numberWidth = this.numberWidth();
            var rect = this.itemRect(index);
            rect.width -= this.textPadding();
            this.changePaintOpacity(this.isEnabled(item));
            this.drawItemName(item, rect.x, rect.y, rect.width - numberWidth);
            this.drawItemNumber(item, rect.x, rect.y, rect.width);
            this.changePaintOpacity(1);
        }
    };
    numberWidth(): number {
        return this.textWidth('000');
    };
    drawItemNumber(item: RPGMakerMV.DataAnyItem|any, x: number, y: number, width: number): void {
        if (this.needsNumber()) {
            this.drawText(':', x, y, width - this.textWidth('00'), 'right');
            this.drawText($gameParty.numItems(item), x, y, width, 'right');
        }
    };
    updateHelp(): void {
        this.setHelpWindowItem(this.item());
    };
    refresh(): void {
        this.makeItemList();
        this.createContents();
        this.drawAllItems();
    };
}

//-----------------------------------------------------------------------------
// Window_SkillType
//
// The window for selecting a skill type on the skill screen.

 class Window_SkillType extends Window_Command {
    constructor(x?: number, y?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number): void {
        Window_Command.prototype.initialize.call(this, x, y);
        this._actor = null;
    };
    _actor: Game_Actor;
    _skillWindow: Window_SkillList;

    windowWidth(): number {
        return 240;
    };
    setActor(actor: Game_Actor): void {
        if (this._actor !== actor) {
            this._actor = actor;
            this.refresh();
            this.selectLast();
        }
    };
    numVisibleRows(): number{
        return 4;
    };
    makeCommandList(): void {
        if (this._actor) {
            var skillTypes = this._actor.addedSkillTypes();
            skillTypes.sort(function(a, b) {
                return a - b;
            });
            skillTypes.forEach(stypeId => {
                var name = $dataSystem.skillTypes[stypeId];
                this.addCommand(name, 'skill', true, stypeId);
            });
        }
    };
    update(): void {
        Window_Command.prototype.update.call(this);
        if (this._skillWindow) {
            this._skillWindow.setStypeId(this.currentExt());
        }
    };
    setSkillWindow(skillWindow: Window_SkillList): void {
        this._skillWindow = skillWindow;
    };
    selectLast(): void {
        var skill = this._actor.lastMenuSkill();
        if (skill) {
            this.selectExt(skill.stypeId);
        } else {
            this.select(0);
        }
    };
}

//-----------------------------------------------------------------------------
// Window_SkillStatus
//
// The window for displaying the skill user's status on the skill screen.

 class Window_SkillStatus extends Window_Base {
    constructor(x?: number, y?: number, width?: number, height?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, width?: number, height?: number): void{
        Window_Base.prototype.initialize.call(this, x, y, width, height);
        this._actor = null;
    };
    _actor: Game_Actor;

    setActor(actor: Game_Actor): void {
        if (this._actor !== actor) {
            this._actor = actor;
            this.refresh();
        }
    };
    refresh(): void {
        this.contents.clear();
        if (this._actor) {
            var w = this.width - this.padding * 2;
            var h = this.height - this.padding * 2;
            var y = h / 2 - this.lineHeight() * 1.5;
            var width = w - 162 - this.textPadding();
            this.drawActorFace(this._actor, 0, 0, 144, h);
            this.drawActorSimpleStatus(this._actor, 162, y, width);
        }
    };
}

//-----------------------------------------------------------------------------
// Window_SkillList
//
// The window for selecting a skill on the skill screen.

 class Window_SkillList extends Window_Selectable {
    constructor(x?: number, y?: number, width?: number, height?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, width?: number, height?: number): void {
        Window_Selectable.prototype.initialize.call(this, x, y, width, height);
        this._actor = null;
        this._stypeId = 0;
        this._data = [];
    };
    _actor: Game_Actor;
    _stypeId: number;
    _data: RPGMakerMV.DataSkill[];

    setActor(actor: Game_Actor): void {
        if (this._actor !== actor) {
            this._actor = actor;
            this.refresh();
            this.resetScroll();
        }
    };
    setStypeId(stypeId: number): void {
        if (this._stypeId !== stypeId) {
            this._stypeId = stypeId;
            this.refresh();
            this.resetScroll();
        }
    };
    maxCols(): number {
        return 2;
    };
    spacing(): number {
        return 48;
    };
    maxItems(): number {
        return this._data ? this._data.length : 1;
    };
    item(): RPGMakerMV.DataSkill {
        return this._data && this.index() >= 0 ? this._data[this.index()] : null;
    };
    isCurrentItemEnabled(): boolean {
        return this.isEnabled(this._data[this.index()]);
    };
    includes(item: RPGMakerMV.DataSkill): boolean {
        return item && item.stypeId === this._stypeId;
    };
    isEnabled(item: RPGMakerMV.DataSkill): boolean {
        return this._actor && this._actor.canUse(item);
    };
    makeItemList(): void {
        if (this._actor) {
            this._data = this._actor.skills().filter(item => {
                return this.includes(item);
            }, this);
        } else {
            this._data = [];
        }
    };
    selectLast(): void {
        var skill;
        if ($gameParty.inBattle()) {
            skill = this._actor.lastBattleSkill();
        } else {
            skill = this._actor.lastMenuSkill();
        }
        var index = this._data.indexOf(skill);
        this.select(index >= 0 ? index : 0);
    };
    drawItem(index: number): void {
        var skill = this._data[index];
        if (skill) {
            var costWidth = this.costWidth();
            var rect = this.itemRect(index);
            rect.width -= this.textPadding();
            this.changePaintOpacity(this.isEnabled(skill));
            this.drawItemName(skill, rect.x, rect.y, rect.width - costWidth);
            this.drawSkillCost(skill, rect.x, rect.y, rect.width);
            this.changePaintOpacity(1);
        }
    };
    costWidth(): number {
        return this.textWidth('000');
    };
    drawSkillCost(skill: RPGMakerMV.DataSkill|any, x: number, y: number, width: number): void {
        if (this._actor.skillTpCost(skill) > 0) {
            this.changeTextColor(this.tpCostColor());
            this.drawText(this._actor.skillTpCost(skill), x, y, width, 'right');
        } else if (this._actor.skillMpCost(skill) > 0) {
            this.changeTextColor(this.mpCostColor());
            this.drawText(this._actor.skillMpCost(skill), x, y, width, 'right');
        }
    };
    updateHelp(): void {
        this.setHelpWindowItem(this.item());
    };
    refresh(): void {
        this.makeItemList();
        this.createContents();
        this.drawAllItems();
    };
}

//-----------------------------------------------------------------------------
// Window_EquipStatus
//
// The window for displaying parameter changes on the equipment screen.

 class Window_EquipStatus extends Window_Base {
    constructor(x?: number, y?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number): void {
        var width = this.windowWidth();
        var height = this.windowHeight();
        Window_Base.prototype.initialize.call(this, x, y, width, height);
        this._actor = null;
        this._tempActor = null;
        this.refresh();
    };
    _actor: Game_Actor;
    _tempActor: Game_Actor;

    windowWidth(): number{
        return 312;
    };
    windowHeight(): number{
        return this.fittingHeight(this.numVisibleRows());
    };
    numVisibleRows(): number{
        return 7;
    };
    setActor(actor: Game_Actor): void{
        if (this._actor !== actor) {
            this._actor = actor;
            this.refresh();
        }
    };
    refresh(): void{
        this.contents.clear();
        if (this._actor) {
            this.drawActorName(this._actor, this.textPadding(), 0);
            for (var i = 0; i < 6; i++) {
                this.drawItem(0, this.lineHeight() * (1 + i), 2 + i);
            }
        }
    };
    setTempActor(tempActor: Game_Actor): void{
        if (this._tempActor !== tempActor) {
            this._tempActor = tempActor;
            this.refresh();
        }
    };
    drawItem(x: number, y: number, paramId: number): void{
        this.drawParamName(x + this.textPadding(), y, paramId);
        if (this._actor) {
            this.drawCurrentParam(x + 140, y, paramId);
        }
        this.drawRightArrow(x + 188, y);
        if (this._tempActor) {
            this.drawNewParam(x + 222, y, paramId);
        }
    };
    drawParamName(x: number, y: number, paramId: number): void {
        this.changeTextColor(this.systemColor());
        this.drawText(TextManager.param(paramId), x, y, 120);
    };
    drawCurrentParam(x: number, y: number, paramId: number): void {
        this.resetTextColor();
        this.drawText(this._actor.param(paramId), x, y, 48, 'right');
    };
    drawRightArrow(x: number, y: number): void{
        this.changeTextColor(this.systemColor());
        this.drawText('\u2192', x, y, 32, 'center');
    };
    drawNewParam(x: number, y: number, paramId: number): void{
        var newValue = this._tempActor.param(paramId);
        var diffvalue = newValue - this._actor.param(paramId);
        this.changeTextColor(this.paramchangeTextColor(diffvalue));
        this.drawText(newValue, x, y, 48, 'right');
    };
}

//-----------------------------------------------------------------------------
// Window_EquipCommand
//
// The window for selecting a command on the equipment screen.

 class Window_EquipCommand extends Window_HorzCommand {
    constructor(x?: number, y?: number, width?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, width?: number): void{
        this._windowWidth = width;
        Window_HorzCommand.prototype.initialize.call(this, x, y);
    };
    _windowWidth: number;

    windowWidth(): number {
        return this._windowWidth;
    };
    maxCols(): number {
        return 3;
    };
    makeCommandList(): void{
        this.addCommand(TextManager.equip2,   'equip');
        this.addCommand(TextManager.optimize, 'optimize');
        this.addCommand(TextManager.clear,    'clear');
    };
}

//-----------------------------------------------------------------------------
// Window_EquipSlot
//
// The window for selecting an equipment slot on the equipment screen.

 class Window_EquipSlot extends Window_Selectable {
    constructor(x?: number, y?: number, width?: number, height?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, width?: number, height?: number): void{
        Window_Selectable.prototype.initialize.call(this, x, y, width, height);
        this._actor = null;
        this.refresh();
    };
    _actor: Game_Actor;

    setActor(actor: Game_Actor): void {
        if (this._actor !== actor) {
            this._actor = actor;
            this.refresh();
        }
    };
    update(): void {
        Window_Selectable.prototype.update.call(this);
        if (this._itemWindow) {
            this._itemWindow.setSlotId(this.index());
        }
    };
    maxItems(): number {
        return this._actor ? this._actor.equipSlots().length : 0;
    };
    item(): RPGMakerMV.DataSkill {
        return this._actor ? this._actor.equips()[this.index()] : null;
    };
    drawItem(index: number): void {
        if (this._actor) {
            var rect = this.itemRectForText(index);
            this.changeTextColor(this.systemColor());
            this.changePaintOpacity(this.isEnabled(index));
            this.drawText(this.slotName(index), rect.x, rect.y, 138, this.lineHeight());
            this.drawItemName(this._actor.equips()[index], rect.x + 138, rect.y);
            this.changePaintOpacity(true);
        }
    };
    slotName(index: number): string {
        var slots = this._actor.equipSlots();
        return this._actor ? $dataSystem.equipTypes[slots[index]] : '';
    };
    isEnabled(index: number): boolean {
        return this._actor ? this._actor.isEquipChangeOk(index) : false;
    };
    isCurrentItemEnabled(): boolean {
        return this.isEnabled(this.index());
    };
    setStatusWindow(statusWindow: Window_EquipStatus): void {
        this._statusWindow = statusWindow;
        this.callUpdateHelp();
    };
    _statusWindow: Window_EquipStatus;
    setItemWindow(itemWindow: Window_EquipItem): void {
        this._itemWindow = itemWindow;
    };
    _itemWindow: Window_EquipItem;
    updateHelp(): void {
        Window_Selectable.prototype.updateHelp.call(this);
        this.setHelpWindowItem(this.item());
        if (this._statusWindow) {
            this._statusWindow.setTempActor(null);
        }
    };
}

//-----------------------------------------------------------------------------
// Window_EquipItem
//
// The window for selecting an equipment item on the equipment screen.

 class Window_EquipItem extends Window_ItemList {
    constructor(x?: number, y?: number, width?: number, height?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, width?: number, height?: number): void {
        Window_ItemList.prototype.initialize.call(this, x, y, width, height);
        this._actor = null;
        this._slotId = 0;
    };
    _actor: Game_Actor;
    _slotId: number;

    setActor(actor: Game_Actor): void {
        if (this._actor !== actor) {
            this._actor = actor;
            this.refresh();
            this.resetScroll();
        }
    };
    setSlotId(slotId: number): void {
        if (this._slotId !== slotId) {
            this._slotId = slotId;
            this.refresh();
            this.resetScroll();
        }
    };
    includes(item: RPGMakerMV.DataAnyItem|any): boolean {
        if (item === null) {
            return true;
        }
        if (this._slotId < 0 || item.etypeId !== this._actor.equipSlots()[this._slotId]) {
            return false;
        }
        return this._actor.canEquip(item);
    };
    isEnabled(item: RPGMakerMV.DataAnyItem): boolean {
        return true;
    };
    selectLast(): void {
    };
    setStatusWindow(statusWindow: Window_EquipStatus): void {
        this._statusWindow = statusWindow;
        this.callUpdateHelp();
    };
    _statusWindow: Window_EquipStatus;
    updateHelp(): void {
        Window_ItemList.prototype.updateHelp.call(this);
        if (this._actor && this._statusWindow) {
            var actor = JsonEx.makeDeepCopy(this._actor);
            actor.forceChangeEquip(this._slotId, this.item());
            this._statusWindow.setTempActor(actor);
        }
    };
    playOkSound(): void {
    };
}

//-----------------------------------------------------------------------------
// Window_Status
//
// The window for displaying full status on the status screen.

 class Window_Status extends Window_Selectable {
    constructor(){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(): void {
        var width = Graphics.boxWidth;
        var height = Graphics.boxHeight;
        Window_Selectable.prototype.initialize.call(this, 0, 0, width, height);
        this._actor = null;
        this.refresh();
        this.activate();
    };
    _actor: Game_Actor;
    setActor(actor: Game_Actor): void {
        if (this._actor !== actor) {
            this._actor = actor;
            this.refresh();
        }
    };
    refresh(): void {
        this.contents.clear();
        if (this._actor) {
            var lineHeight = this.lineHeight();
            this.drawBlock1(lineHeight * 0);
            this.drawHorzLine(lineHeight * 1);
            this.drawBlock2(lineHeight * 2);
            this.drawHorzLine(lineHeight * 6);
            this.drawBlock3(lineHeight * 7);
            this.drawHorzLine(lineHeight * 13);
            this.drawBlock4(lineHeight * 14);
        }
    };
    drawBlock1(y: number): void {
        this.drawActorName(this._actor, 6, y);
        this.drawActorClass(this._actor, 192, y);
        this.drawActorNickname(this._actor, 432, y);
    };
    drawBlock2(y: number): void {
        this.drawActorFace(this._actor, 12, y);
        this.drawBasicInfo(204, y);
        this.drawExpInfo(456, y);
    };
    drawBlock3(y: number): void {
        this.drawParameters(48, y);
        this.drawEquipments(432, y);
    };
    drawBlock4(y: number): void {
        this.drawProfile(6, y);
    };
    drawHorzLine(y: number): void {
        var lineY = y + this.lineHeight() / 2 - 1;
        this.contents.paintOpacity = 48;
        this.contents.fillRect(0, lineY, this.contentsWidth(), 2, this.lineColor());
        this.contents.paintOpacity = 255;
    };
    lineColor(): string {
        return this.normalColor();
    };
    drawBasicInfo(x: number, y: number): void{
        var lineHeight = this.lineHeight();
        this.drawActorLevel(this._actor, x, y + lineHeight * 0);
        this.drawActorIcons(this._actor, x, y + lineHeight * 1);
        this.drawActorHp(this._actor, x, y + lineHeight * 2);
        this.drawActorMp(this._actor, x, y + lineHeight * 3);
    };
    drawParameters(x: number, y: number): void {
        var lineHeight = this.lineHeight();
        for (var i = 0; i < 6; i++) {
            var paramId = i + 2;
            var y2 = y + lineHeight * i;
            this.changeTextColor(this.systemColor());
            this.drawText(TextManager.param(paramId), x, y2, 160);
            this.resetTextColor();
            this.drawText(this._actor.param(paramId), x + 160, y2, 60, 'right');
        }
    };
    drawExpInfo(x: number, y: number): void {
        var lineHeight = this.lineHeight();
        var expTotal = TextManager.expTotal.format(TextManager.exp);
        var expNext = TextManager.expNext.format(TextManager.level);
        var value1:any = this._actor.currentExp();
        var value2:any = this._actor.nextRequiredExp();
        if (this._actor.isMaxLevel()) {
            value1 = '-------';
            value2 = '-------';
        }
        this.changeTextColor(this.systemColor());
        this.drawText(expTotal, x, y + lineHeight * 0, 270);
        this.drawText(expNext, x, y + lineHeight * 2, 270);
        this.resetTextColor();
        this.drawText(value1, x, y + lineHeight * 1, 270, 'right');
        this.drawText(value2, x, y + lineHeight * 3, 270, 'right');
    };
    drawEquipments(x: number, y: number): void {
        var equips = this._actor.equips();
        var count = Math.min(equips.length, this.maxEquipmentLines());
        for (var i = 0; i < count; i++) {
            this.drawItemName(equips[i], x, y + this.lineHeight() * i);
        }
    };
    drawProfile(x: number, y: number): void {
        this.drawTextEx(this._actor.profile(), x, y);
    };
    maxEquipmentLines(): number {
        return 6;
    };
}

//-----------------------------------------------------------------------------
// Window_Options
//
// The window for changing various settings on the options screen.

 class Window_Options extends Window_Command {
    constructor(){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(): void {
        Window_Command.prototype.initialize.call(this, 0, 0);
        this.updatePlacement();
    };
    windowWidth(): number {
        return 400;
    };
    windowHeight(): number {
        return this.fittingHeight(Math.min(this.numVisibleRows(), 12));
    };
    updatePlacement(): void {
        this.x = (Graphics.boxWidth - this.width) / 2;
        this.y = (Graphics.boxHeight - this.height) / 2;
    };
    makeCommandList(): void {
        this.addGeneralOptions();
        this.addVolumeOptions();
    };
    addGeneralOptions(): void {
        this.addCommand(TextManager.alwaysDash, 'alwaysDash');
        this.addCommand(TextManager.commandRemember, 'commandRemember');
    };
    addVolumeOptions(): void {
        this.addCommand(TextManager.bgmVolume, 'bgmVolume');
        this.addCommand(TextManager.bgsVolume, 'bgsVolume');
        this.addCommand(TextManager.meVolume, 'meVolume');
        this.addCommand(TextManager.seVolume, 'seVolume');
    };
    drawItem(index: number): void {
        var rect = this.itemRectForText(index);
        var statusWidth = this.statusWidth();
        var titleWidth = rect.width - statusWidth;
        this.resetTextColor();
        this.changePaintOpacity(this.isCommandEnabled(index));
        this.drawText(this.commandName(index), rect.x, rect.y, titleWidth, 'left');
        this.drawText(this.statusText(index), titleWidth, rect.y, statusWidth, 'right');
    };
    statusWidth(): number {
        return 120;
    };
    statusText(index: number): string {
        var symbol = this.commandSymbol(index);
        var value:any = this.getConfigValue(symbol);
        if (this.isVolumeSymbol(symbol)) {
            return this.volumeStatusText(value);
        } else {
            return this.booleanStatusText(value);
        }
    };
    isVolumeSymbol(symbol: string): boolean {
        return symbol.contains('Volume');
    };
    booleanStatusText(value: number): string {
        return value ? 'ON' : 'OFF';
    };
    volumeStatusText(value: number): string {
        return value + '%';
    };
    processOk(): void {
        var index = this.index();
        var symbol = this.commandSymbol(index);
        var value:any = this.getConfigValue(symbol);
        if (this.isVolumeSymbol(symbol)) {
            value += this.volumeOffset();
            if (value > 100) {
                value = 0;
            }
            value = value.clamp(0, 100);
            this.changeValue(symbol, value);
        } else {
            this.changeValue(symbol, !value);
        }
    };
    cursorRight(wrap: boolean): void {
        var index = this.index();
        var symbol = this.commandSymbol(index);
        var value:any = this.getConfigValue(symbol);
        if (this.isVolumeSymbol(symbol)) {
            value += this.volumeOffset();
            value = value.clamp(0, 100);
            this.changeValue(symbol, value);
        } else {
            this.changeValue(symbol, true);
        }
    };
    cursorLeft(wrap: boolean): void {
        var index = this.index();
        var symbol = this.commandSymbol(index);
        var value:any = this.getConfigValue(symbol);
        if (this.isVolumeSymbol(symbol)) {
            value -= this.volumeOffset();
            value = value.clamp(0, 100);
            this.changeValue(symbol, value);
        } else {
            this.changeValue(symbol, false);
        }
    };
    volumeOffset(): number {
        return 20;
    };
    changeValue(symbol: string, value: number|any): void {
        var lastValue = this.getConfigValue(symbol);
        if (lastValue !== value) {
            this.setConfigValue(symbol, value);
            this.redrawItem(this.findSymbol(symbol));
            SoundManager.playCursor();
        }
    };
    getConfigValue(symbol: string): number | boolean {
        return ConfigManager[symbol];
    };
    setConfigValue(symbol: string, volume: number | boolean): void {
        ConfigManager[symbol] = volume;
    };
}

//-----------------------------------------------------------------------------
// Window_SavefileList
//
// The window for selecting a save file on the save and load screens.

 class Window_SavefileList extends Window_Selectable {
    constructor(x?: number, y?: number, width?: number, height?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, width?: number, height?: number): void{
        Window_Selectable.prototype.initialize.call(this, x, y, width, height);
        this.activate();
        this._mode = null;
    };
    _mode: string;
    setMode(mode: string): void {
        this._mode = mode;
    };
    maxItems(): number {
        return DataManager.maxSavefiles();
    };
    maxVisibleItems(): number {
        return 5;
    };
    itemHeight(): number {
        var innerHeight = this.height - this.padding * 2;
        return Math.floor(innerHeight / this.maxVisibleItems());
    };
    drawItem(index: number): void {
        var id = index + 1;
        var valid = DataManager.isThisGameFile(id);
        var info = DataManager.loadSavefileInfo(id);
        var rect = this.itemRectForText(index);
        this.resetTextColor();
        if (this._mode === 'load') {
            this.changePaintOpacity(valid);
        }
        this.drawFileId(id, rect.x, rect.y);
        if (info) {
            this.changePaintOpacity(valid);
            this.drawContents(info, rect, valid);
            this.changePaintOpacity(true);
        }
    };
    drawFileId(id: number, x: number, y: number): void {
        this.drawText(TextManager.file + ' ' + id, x, y, 180);
    };
    drawContents(info: RPGMakerMV.SavefileInfo, rect: Rectangle, valid: boolean): void {
        var bottom = rect.y + rect.height;
        if (rect.width >= 420) {
            this.drawGameTitle(info, rect.x + 192, rect.y, rect.width - 192);
            if (valid) {
                this.drawPartyCharacters(info, rect.x + 220, bottom - 4);
            }
        }
        var lineHeight = this.lineHeight();
        var y2 = bottom - lineHeight;
        if (y2 >= lineHeight) {
            this.drawPlaytime(info, rect.x, y2, rect.width);
        }
    };
    drawGameTitle(info: RPGMakerMV.SavefileInfo, x: number, y: number, width: number): void {
        if (info.title) {
            this.drawText(info.title, x, y, width);
        }
    };
    drawPartyCharacters(info: RPGMakerMV.SavefileInfo, x: number, y: number): void {
        if (info.characters) {
            for (var i = 0; i < info.characters.length; i++) {
                var data = info.characters[i];
                this.drawCharacter(data[0], data[1], x + i * 48, y);
            }
        }
    };
    drawPlaytime(info: RPGMakerMV.SavefileInfo, x: number, y: number, width: number): void {
        if (info.playtime) {
            this.drawText(info.playtime, x, y, width, 'right');
        }
    };
    playOkSound(): void{
    };
}

//-----------------------------------------------------------------------------
// Window_ShopCommand
//
// The window for selecting buy/sell on the shop screen.

 class Window_ShopCommand extends Window_HorzCommand {
    constructor(width?: number, purchaseOnly?: boolean){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(width?: number, purchaseOnly?: boolean|any): void{
        this._windowWidth = width;
        this._purchaseOnly = purchaseOnly;
        Window_HorzCommand.prototype.initialize.call(this, 0, 0);
    };
    _windowWidth: number;
    _purchaseOnly: boolean;
    windowWidth(): number{
        return this._windowWidth;
    };
    maxCols(): number{
        return 3;
    };
    makeCommandList(): void{
        this.addCommand(TextManager.buy,    'buy');
        this.addCommand(TextManager.sell,   'sell',   !this._purchaseOnly);
        this.addCommand(TextManager.cancel, 'cancel');
    };
}

//-----------------------------------------------------------------------------
// Window_ShopBuy
//
// The window for selecting an item to buy on the shop screen.

 class Window_ShopBuy extends Window_Selectable {
    constructor(x?: number, y?: number, height?: number, shopGoods?: any[][]){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, height?: number, shopGoods?: any[][]|any): void {
        var width = this.windowWidth();
        Window_Selectable.prototype.initialize.call(this, x, y, width, height);
        this._shopGoods = shopGoods;
        this._money = 0;
        this.refresh();
        this.select(0);
    };
    _shopGoods: any[][];
    _money: number;
    windowWidth(): number{
        return 456;
    };
    maxItems(): number{
        return this._data ? this._data.length : 1;
    };
    item(): RPGMakerMV.DataAnyItem{
        return this._data[this.index()];
    };
    setMoney(money: number): void{
        this._money = money;
        this.refresh();
    };
    isCurrentItemEnabled(): boolean {
        return this.isEnabled(this._data[this.index()]);
    };
    price(item: RPGMakerMV.DataAnyItem): number {
        return this._price[this._data.indexOf(item)] || 0;
    };
    isEnabled(item: RPGMakerMV.DataAnyItem): boolean {
        return (item && this.price(item) <= this._money &&
                !$gameParty.hasMaxItems(item));
    };
    refresh(): void{
        this.makeItemList();
        this.createContents();
        this.drawAllItems();
    };
    makeItemList(): void {
        this._data = [];
        this._price = [];
        this._shopGoods.forEach(goods => {
            var item = null;
            switch (goods[0]) {
            case 0:
                item = $dataItems[goods[1]];
                break;
            case 1:
                item = $dataWeapons[goods[1]];
                break;
            case 2:
                item = $dataArmors[goods[1]];
                break;
            }
            if (item) {
                this._data.push(item);
                this._price.push(goods[2] === 0 ? item.price : goods[3]);
            }
        }, this);
    };
    _data: RPGMakerMV.DataAnyItem[];
    _price: number[];
    drawItem(index: number): void {
        var item = this._data[index];
        var rect = this.itemRect(index);
        var priceWidth = 96;
        rect.width -= this.textPadding();
        this.changePaintOpacity(this.isEnabled(item));
        this.drawItemName(item, rect.x, rect.y, rect.width - priceWidth);
        this.drawText(this.price(item), rect.x + rect.width - priceWidth,
                      rect.y, priceWidth, 'right');
        this.changePaintOpacity(true);
    };
    setStatusWindow(statusWindow: Window_EquipStatus|any): void {
        this._statusWindow = statusWindow;
        this.callUpdateHelp();
    };
    _statusWindow: Window_EquipStatus|any;
    updateHelp(): void {
        this.setHelpWindowItem(this.item());
        if (this._statusWindow) {
            this._statusWindow.setItem(this.item());
        }
    };
}

//-----------------------------------------------------------------------------
// Window_ShopSell
//
// The window for selecting an item to sell on the shop screen.

 class Window_ShopSell extends Window_ItemList {
    constructor(x?: number, y?: number, width?: number, height?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, width?: number, height?: number): void {
        Window_ItemList.prototype.initialize.call(this, x, y, width, height);
    };
    isEnabled(item: RPGMakerMV.DataAnyItem): boolean{
        return item && item.price > 0;
    };
}

//-----------------------------------------------------------------------------
// Window_ShopNumber
//
// The window for inputting quantity of items to buy or sell on the shop
// screen.

 class Window_ShopNumber extends Window_Selectable {
    constructor(x?: number, y?: number, height?: number) {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, height?: number): void {
        var width = this.windowWidth();
        Window_Selectable.prototype.initialize.call(this, x, y, width, height);
        this._item = null;
        this._max = 1;
        this._price = 0;
        this._number = 1;
        this._currencyUnit = TextManager.currencyUnit;
        this.createButtons();
    };
    _item: RPGMakerMV.DataAnyItem;
    _max: number;
    _price: number;
    _number: number;
    _currencyUnit: string;
    windowWidth(): number {
        return 456;
    };
    number(): number {
        return this._number;
    };
    setup(item: RPGMakerMV.DataAnyItem, max: number, price: number): void {
        this._item = item;
        this._max = Math.floor(max);
        this._price = price;
        this._number = 1;
        this.placeButtons();
        this.updateButtonsVisiblity();
        this.refresh();
    };
    setCurrencyUnit(currencyUnit: string): void {
        this._currencyUnit = currencyUnit;
        this.refresh();
    };
    createButtons(): void {
        var bitmap = ImageManager.loadSystem('ButtonSet');
        var buttonWidth = 48;
        var buttonHeight = 48;
        this._buttons = [];
        for (var i = 0; i < 5; i++) {
            var button = new Sprite_Button();
            var x = buttonWidth * i;
            var w = buttonWidth * (i === 4 ? 2 : 1);
            button.bitmap = bitmap;
            button.setColdFrame(x, 0, w, buttonHeight);
            button.setHotFrame(x, buttonHeight, w, buttonHeight);
            button.visible = false;
            this._buttons.push(button);
            this.addChild(button);
        }
        this._buttons[0].setClickHandler(this.onButtonDown2.bind(this));
        this._buttons[1].setClickHandler(this.onButtonDown.bind(this));
        this._buttons[2].setClickHandler(this.onButtonUp.bind(this));
        this._buttons[3].setClickHandler(this.onButtonUp2.bind(this));
        this._buttons[4].setClickHandler(this.onButtonOk.bind(this));
    };
    _buttons: Sprite_Button[];
    placeButtons(): void {
        var numButtons = this._buttons.length;
        var spacing = 16;
        var totalWidth = -spacing;
        for (var i = 0; i < numButtons; i++) {
            totalWidth += this._buttons[i].width + spacing;
        }
        var x = (this.width - totalWidth) / 2;
        for (var j = 0; j < numButtons; j++) {
            var button = this._buttons[j];
            button.x = x;
            button.y = this.buttonY();
            x += button.width + spacing;
        }
    };
    updateButtonsVisiblity(): void {
        if (TouchInput.date > Input.date) {
            this.showButtons();
        } else {
            this.hideButtons();
        }
    };
    showButtons(): void {
        for (var i = 0; i < this._buttons.length; i++) {
            this._buttons[i].visible = true;
        }
    };
    hideButtons(): void {
        for (var i = 0; i < this._buttons.length; i++) {
            this._buttons[i].visible = false;
        }
    };
    refresh(): void {
        this.contents.clear();
        this.drawItemName(this._item, 0, this.itemY());
        this.drawMultiplicationSign();
        this.drawNumber();
        this.drawTotalPrice();
    };
    drawMultiplicationSign(): void {
        var sign = '\u00d7';
        var width = this.textWidth(sign);
        var x = this.cursorX() - width * 2;
        var y = this.itemY();
        this.resetTextColor();
        this.drawText(sign, x, y, width);
    };
    drawNumber(): void {
        var x = this.cursorX();
        var y = this.itemY();
        var width = this.cursorWidth() - this.textPadding();
        this.resetTextColor();
        this.drawText(this._number, x, y, width, 'right');
    };
    drawTotalPrice(): void {
        var total = this._price * this._number;
        var width = this.contentsWidth() - this.textPadding();
        this.drawCurrencyValue(total, this._currencyUnit, 0, this.priceY(), width);
    };
    itemY(): number {
        return Math.round(this.contentsHeight() / 2 - this.lineHeight() * 1.5);
    };
    priceY(): number {
        return Math.round(this.contentsHeight() / 2 + this.lineHeight() / 2);
    };
    buttonY(): number {
        return Math.round(this.priceY() + this.lineHeight() * 2.5);
    };
    cursorWidth(): number {
        var digitWidth = this.textWidth('0');
        return this.maxDigits() * digitWidth + this.textPadding() * 2;
    };
    cursorX(): number {
        return this.contentsWidth() - this.cursorWidth() - this.textPadding();
    };
    maxDigits(): number {
        return 2;
    };
    update(): void {
        Window_Selectable.prototype.update.call(this);
        this.processNumberChange();
    };
    isOkTriggered(): boolean {
        return Input.isTriggered('ok');
    };
    playOkSound(): void {
    };
    processNumberChange(): void {
        if (this.isOpenAndActive()) {
            if (Input.isRepeated('right')) {
                this.changeNumber(1);
            }
            if (Input.isRepeated('left')) {
                this.changeNumber(-1);
            }
            if (Input.isRepeated('up')) {
                this.changeNumber(10);
            }
            if (Input.isRepeated('down')) {
                this.changeNumber(-10);
            }
        }
    };
    changeNumber(amount: number): void {
        var lastNumber = this._number;
        this._number = (this._number + amount).clamp(1, this._max);
        if (this._number !== lastNumber) {
            SoundManager.playCursor();
            this.refresh();
        }
    };
    updateCursor(): void {
        this.setCursorRect(this.cursorX(), this.itemY(),
                           this.cursorWidth(), this.lineHeight());
    };
    onButtonUp(): void {
        this.changeNumber(1);
    };
    onButtonUp2(): void {
        this.changeNumber(10);
    };
    onButtonDown(): void {
        this.changeNumber(-1);
    };
    onButtonDown2(): void {
        this.changeNumber(-10);
    };
    onButtonOk(): void {
        this.processOk();
    };
}

//-----------------------------------------------------------------------------
// Window_ShopStatus
//
// The window for displaying number of items in possession and the actor's
// equipment on the shop screen.

 class Window_ShopStatus extends Window_Base {
    constructor(x?: number, y?: number, width?: number, height?: number) {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, width?: number, height?: number): void {
        Window_Base.prototype.initialize.call(this, x, y, width, height);
        this._item = null;
        this._pageIndex = 0;
        this.refresh();
    };
    _item: RPGMakerMV.DataAnyItem|any;
    _pageIndex: number;
    refresh(): void {
        this.contents.clear();
        if (this._item) {
            var x = this.textPadding();
            this.drawPossession(x, 0);
            if (this.isEquipItem()) {
                this.drawEquipInfo(x, this.lineHeight() * 2);
            }
        }
    };
    setItem(item: RPGMakerMV.DataAnyItem): void {
        this._item = item;
        this.refresh();
    };
    isEquipItem(): boolean {
        return DataManager.isWeapon(this._item) || DataManager.isArmor(this._item);
    };
    drawPossession(x: number, y: number): void {
        var width = this.contents.width - this.textPadding() - x;
        var possessionWidth = this.textWidth('0000');
        this.changeTextColor(this.systemColor());
        this.drawText(TextManager.possession, x, y, width - possessionWidth);
        this.resetTextColor();
        this.drawText($gameParty.numItems(this._item), x, y, width, 'right');
    };
    drawEquipInfo(x: number, y: number): void {
        var members = this.statusMembers();
        for (var i = 0; i < members.length; i++) {
            this.drawActorEquipInfo(x, y + this.lineHeight() * (i * 2.4), members[i]);
        }
    };
    statusMembers(): Game_Actor[] {
        var start = this._pageIndex * this.pageSize();
        var end = start + this.pageSize();
        return $gameParty.members().slice(start, end);
    };
    pageSize(): number {
        return 4;
    };
    maxPages(): number {
        return Math.floor(($gameParty.size() + this.pageSize() - 1) / this.pageSize());
    };
    drawActorEquipInfo(x: number, y: number, actor: Game_Actor): void {
        var enabled = actor.canEquip(this._item);
        this.changePaintOpacity(enabled);
        this.resetTextColor();
        this.drawText(actor.name(), x, y, 168);
        var item1 = this.currentEquippedItem(actor, this._item.etypeId);
        if (enabled) {
            this.drawActorParamChange(x, y, actor, item1);
        }
        this.drawItemName(item1, x, y + this.lineHeight());
        this.changePaintOpacity(true);
    };
    drawActorParamChange(x: number, y: number, actor: Game_Actor, item1: RPGMakerMV.DataAnyItem|any): void {
        var width = this.contents.width - this.textPadding() - x;
        var paramId = this.paramId();
        var change = this._item.params[paramId] - (item1 ? item1.params[paramId] : 0);
        this.changeTextColor(this.paramchangeTextColor(change));
        this.drawText((change > 0 ? '+' : '') + change, x, y, width, 'right');
    };
   
    paramId(): number {
        return DataManager.isWeapon(this._item) ? 2 : 3;
    };

    currentEquippedItem(actor: Game_Actor, etypeId: number): RPGMakerMV.DataAnyItem {
        var list = [];
        var equips = actor.equips();
        var slots = actor.equipSlots();
        for (var i = 0; i < slots.length; i++) {
            if (slots[i] === etypeId) {
                list.push(equips[i]);
            }
        }
        var paramId = this.paramId();
        var worstParam = Number.MAX_VALUE;
        var worstItem = null;
        for (var j = 0; j < list.length; j++) {
            if (list[j] && list[j].params[paramId] < worstParam) {
                worstParam = list[j].params[paramId];
                worstItem = list[j];
            }
        }
        return worstItem;
    };

    update(): void {
        Window_Base.prototype.update.call(this);
        this.updatePage();
    };

    updatePage(): void {
        if (this.isPageChangeEnabled() && this.isPageChangeRequested()) {
            this.changePage();
        }
    };
    isPageChangeEnabled(): boolean {
        return this.visible && this.maxPages() >= 2;
    };
    isPageChangeRequested(): boolean {
        if (Input.isTriggered('shift')) {
            return true;
        }
        if (TouchInput.isTriggered() && this.isTouchedInsideFrame()) {
            return true;
        }
        return false;
    };
    isTouchedInsideFrame(): boolean {
        var x = this.canvasToLocalX(TouchInput.x);
        var y = this.canvasToLocalY(TouchInput.y);
        return x >= 0 && y >= 0 && x < this.width && y < this.height;
    };
    changePage(): void {
        this._pageIndex = (this._pageIndex + 1) % this.maxPages();
        this.refresh();
        SoundManager.playCursor();
    };
}

//-----------------------------------------------------------------------------
// Window_NameEdit
//
// The window for editing an actor's name on the name input screen.

 class Window_NameEdit extends Window_Base {
    constructor(actor?: Game_Actor, maxLength?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(actor?: Game_Actor|any, maxLength?: number): void {
        var width = this.windowWidth();
        var height = this.windowHeight();
        var x = (Graphics.boxWidth - width) / 2;
        var y = (Graphics.boxHeight - (height + this.fittingHeight(9) + 8)) / 2;
        Window_Base.prototype.initialize.call(this, x, y, width, height);
        this._actor = actor;
        this._name = actor.name().slice(0, this._maxLength);
        this._index = this._name.length;
        this._maxLength = maxLength;
        this._defaultName = this._name;
        this.deactivate();
        this.refresh();
        ImageManager.reserveFace(actor.faceName());
    };
    _actor: Game_Actor;
    _name: string;
    _index: number;
    _maxLength: number;
    _defaultName: string;
    windowWidth(): number {
        return 480;
    };
    windowHeight(): number {
        return this.fittingHeight(4);
    };
    //@ts-ignore
    name(): string {
        return this._name;
    };
    restoreDefault(): boolean {
        this._name = this._defaultName;
        this._index = this._name.length;
        this.refresh();
        return this._name.length > 0;
    };
    add(ch: string): boolean {
        if (this._index < this._maxLength) {
            this._name += ch;
            this._index++;
            this.refresh();
            return true;
        } else {
            return false;
        }
    };
    back(): boolean {
        if (this._index > 0) {
            this._index--;
            this._name = this._name.slice(0, this._index);
            this.refresh();
            return true;
        } else {
            return false;
        }
    };
    faceWidth(): number {
        return 144;
    };
    charWidth(): number {
        var text = $gameSystem.isJapanese() ? '\uff21' : 'A';
        return this.textWidth(text);
    };
    left(): number {
        var nameCenter = (this.contentsWidth() + this.faceWidth()) / 2;
        var nameWidth = (this._maxLength + 1) * this.charWidth();
        return Math.min(nameCenter - nameWidth / 2, this.contentsWidth() - nameWidth);
    };
    itemRect(index: number): { x: number, y: number, width: number, height: number } {
        return {
            x: this.left() + index * this.charWidth(),
            y: 54,
            width: this.charWidth(),
            height: this.lineHeight()
        };
    };
    underlineRect(index: number): { x: number, y: number, width: number, height: number } {
        var rect = this.itemRect(index);
        rect.x++;
        rect.y += rect.height - 4;
        rect.width -= 2;
        rect.height = 2;
        return rect;
    };
    underlineColor(): string {
        return this.normalColor();
    };
    drawUnderline(index: number): void {
        var rect = this.underlineRect(index);
        var color = this.underlineColor();
        this.contents.paintOpacity = 48;
        this.contents.fillRect(rect.x, rect.y, rect.width, rect.height, color);
        this.contents.paintOpacity = 255;
    };
    drawChar(index: number): void {
        var rect = this.itemRect(index);
        this.resetTextColor();
        this.drawText(this._name[index] || '', rect.x, rect.y);
    };
    refresh(): void {
        this.contents.clear();
        this.drawActorFace(this._actor, 0, 0);
        for (var i = 0; i < this._maxLength; i++) {
            this.drawUnderline(i);
        }
        for (var j = 0; j < this._name.length; j++) {
            this.drawChar(j);
        }
        var rect = this.itemRect(this._index);
        this.setCursorRect(rect.x, rect.y, rect.width, rect.height);
    };
}

//-----------------------------------------------------------------------------
// Window_NameInput
//
// The window for selecting text characters on the name input screen.

 class Window_NameInput extends Window_Selectable {
    constructor(editWindow?: Window_NameEdit) {
        super();
        this.initialize.apply(this, arguments);
    }

    static LATIN1: RPGMakerMV.NameInputLatin1=
    [ 'A','B','C','D','E',  'a','b','c','d','e',
      'F','G','H','I','J',  'f','g','h','i','j',
      'K','L','M','N','O',  'k','l','m','n','o',
      'P','Q','R','S','T',  'p','q','r','s','t',
      'U','V','W','X','Y',  'u','v','w','x','y',
      'Z','[',']','^','_',  'z','{','}','|','~',
      '0','1','2','3','4',  '!','#','$','%','&',
      '5','6','7','8','9',  '(',')','*','+','-',
      '/','=','@','<','>',  ':',';',' ','Page','OK' ];
    static LATIN2: RPGMakerMV.NameInputLatin2 =
    [ 'Á','É','Í','Ó','Ú',  'á','é','í','ó','ú',
      'À','È','Ì','Ò','Ù',  'à','è','ì','ò','ù',
      'Â','Ê','Î','Ô','Û',  'â','ê','î','ô','û',
      'Ä','Ë','Ï','Ö','Ü',  'ä','ë','ï','ö','ü',
      'Ā','Ē','Ī','Ō','Ū',  'ā','ē','ī','ō','ū',
      'Ã','Å','Æ','Ç','Ð',  'ã','å','æ','ç','ð',
      'Ñ','Õ','Ø','Š','Ŵ',  'ñ','õ','ø','š','ŵ',
      'Ý','Ŷ','Ÿ','Ž','Þ',  'ý','ÿ','ŷ','ž','þ',
      'Ĳ','Œ','ĳ','œ','ß',  '«','»',' ','Page','OK' ];
    static RUSSIA: RPGMakerMV.NameInputCyrillic =
    [ 'А','Б','В','Г','Д',  'а','б','в','г','д',
      'Е','Ё','Ж','З','И',  'е','ё','ж','з','и',
      'Й','К','Л','М','Н',  'й','к','л','м','н',
      'О','П','Р','С','Т',  'о','п','р','с','т',
      'У','Ф','Х','Ц','Ч',  'у','ф','х','ц','ч',
      'Ш','Щ','Ъ','Ы','Ь',  'ш','щ','ъ','ы','ь',
      'Э','Ю','Я','^','_',  'э','ю','я','%','&',
      '0','1','2','3','4',  '(',')','*','+','-',
      '5','6','7','8','9',  ':',';',' ','','OK' ];
    static JAPAN1: RPGMakerMV.NameInputHiragana =
    [ 'あ','い','う','え','お',  'が','ぎ','ぐ','げ','ご',
      'か','き','く','け','こ',  'ざ','じ','ず','ぜ','ぞ',
      'さ','し','す','せ','そ',  'だ','ぢ','づ','で','ど',
      'た','ち','つ','て','と',  'ば','び','ぶ','べ','ぼ',
      'な','に','ぬ','ね','の',  'ぱ','ぴ','ぷ','ぺ','ぽ',
      'は','ひ','ふ','へ','ほ',  'ぁ','ぃ','ぅ','ぇ','ぉ',
      'ま','み','む','め','も',  'っ','ゃ','ゅ','ょ','ゎ',
      'や','ゆ','よ','わ','ん',  'ー','～','・','＝','☆',
      'ら','り','る','れ','ろ',  'ゔ','を','　','カナ','決定' ];
    static JAPAN2: RPGMakerMV.NameInputKatakana =
    [ 'ア','イ','ウ','エ','オ',  'ガ','ギ','グ','ゲ','ゴ',
      'カ','キ','ク','ケ','コ',  'ザ','ジ','ズ','ゼ','ゾ',
      'サ','シ','ス','セ','ソ',  'ダ','ヂ','ヅ','デ','ド',
      'タ','チ','ツ','テ','ト',  'バ','ビ','ブ','ベ','ボ',
      'ナ','ニ','ヌ','ネ','ノ',  'パ','ピ','プ','ペ','ポ',
      'ハ','ヒ','フ','ヘ','ホ',  'ァ','ィ','ゥ','ェ','ォ',
      'マ','ミ','ム','メ','モ',  'ッ','ャ','ュ','ョ','ヮ',
      'ヤ','ユ','ヨ','ワ','ン',  'ー','～','・','＝','☆',
      'ラ','リ','ル','レ','ロ',  'ヴ','ヲ','　','英数','決定' ];
    static JAPAN3: RPGMakerMV.NameInputFullwidthLatin =
    [ 'Ａ','Ｂ','Ｃ','Ｄ','Ｅ',  'ａ','ｂ','ｃ','ｄ','ｅ',
      'Ｆ','Ｇ','Ｈ','Ｉ','Ｊ',  'ｆ','ｇ','ｈ','ｉ','ｊ',
      'Ｋ','Ｌ','Ｍ','Ｎ','Ｏ',  'ｋ','ｌ','ｍ','ｎ','ｏ',
      'Ｐ','Ｑ','Ｒ','Ｓ','Ｔ',  'ｐ','ｑ','ｒ','ｓ','ｔ',
      'Ｕ','Ｖ','Ｗ','Ｘ','Ｙ',  'ｕ','ｖ','ｗ','ｘ','ｙ',
      'Ｚ','［','］','＾','＿',  'ｚ','｛','｝','｜','～',
      '０','１','２','３','４',  '！','＃','＄','％','＆',
      '５','６','７','８','９',  '（','）','＊','＋','－',
      '／','＝','＠','＜','＞',  '：','；','　','かな','決定' ];

    initialize(editWindow?: Window_NameEdit|any): void {
        var x = editWindow.x;
        var y = editWindow.y + editWindow.height + 8;
        var width = editWindow.width;
        var height = this.windowHeight();
        Window_Selectable.prototype.initialize.call(this, x, y, width, height);
        this._editWindow = editWindow;
        this._page = 0;
        this._index = 0;
        this.refresh();
        this.updateCursor();
        this.activate();
    };
    _editWindow: Window_NameEdit;
    _page: number;
    _index: number;

    windowHeight(): number {
        return this.fittingHeight(9);
    };
    table(): string[][] {
        if ($gameSystem.isJapanese()) {
            return [Window_NameInput.JAPAN1,
                    Window_NameInput.JAPAN2,
                    Window_NameInput.JAPAN3];
        } else if ($gameSystem.isRussian()) {
            return [Window_NameInput.RUSSIA];
        } else {
            return [Window_NameInput.LATIN1,
                    Window_NameInput.LATIN2];
        }
    };
    maxCols(): number {
        return 10;
    };
    maxItems(): number {
        return 90;
    };
    character(): string {
        return this._index < 88 ? this.table()[this._page][this._index] : '';
    };
    isPageChange(): boolean {
        return this._index === 88;
    };
    isOk(): boolean {
        return this._index === 89;
    };
    itemRect(index: number): Rectangle|any {
        return {
            x: index % 10 * 42 + Math.floor(index % 10 / 5) * 24,
            y: Math.floor(index / 10) * this.lineHeight(),
            width: 42,
            height: this.lineHeight()
        };
    };
    refresh(): void {
        var table = this.table();
        this.contents.clear();
        this.resetTextColor();
        for (var i = 0; i < 90; i++) {
            var rect = this.itemRect(i);
            rect.x += 3;
            rect.width -= 6;
            this.drawText(table[this._page][i], rect.x, rect.y, rect.width, 'center');
        }
    };
    updateCursor(): void {
        var rect = this.itemRect(this._index);
        this.setCursorRect(rect.x, rect.y, rect.width, rect.height);
    };
    isCursorMovable(): boolean {
        return this.active;
    };
    cursorDown(wrap: boolean): void {
        if (this._index < 80 || wrap) {
            this._index = (this._index + 10) % 90;
        }
    };
    cursorUp(wrap: boolean): void {
        if (this._index >= 10 || wrap) {
            this._index = (this._index + 80) % 90;
        }
    };
    cursorRight(wrap: boolean): void {
        if (this._index % 10 < 9) {
            this._index++;
        } else if (wrap) {
            this._index -= 9;
        }
    };
    cursorLeft(wrap: boolean): void {
        if (this._index % 10 > 0) {
            this._index--;
        } else if (wrap) {
            this._index += 9;
        }
    };
    cursorPagedown(): void {
        this._page = (this._page + 1) % this.table().length;
        this.refresh();
    };
    cursorPageup(): void {
        this._page = (this._page + this.table().length - 1) % this.table().length;
        this.refresh();
    };
    processCursorMove(): void {
        var lastPage = this._page;
        Window_Selectable.prototype.processCursorMove.call(this);
        this.updateCursor();
        if (this._page !== lastPage) {
            SoundManager.playCursor();
        }
    };
    
    processHandling(): void {
        if (this.isOpen() && this.active) {
            if (Input.isTriggered('shift')) {
                this.processJump();
            }
            if (Input.isRepeated('cancel')) {
                this.processBack();
            }
            if (Input.isRepeated('ok')) {
                this.processOk();
            }
        }
    };
    isCancelEnabled(): boolean {
        return true;
    };
    processCancel(): void {
        this.processBack();
    };
    processJump(): void {
        if (this._index !== 89) {
            this._index = 89;
            SoundManager.playCursor();
        }
    };
    processBack(): void {
        if (this._editWindow.back()) {
            SoundManager.playCancel();
        }
    };
    processOk(): void {
        if (this.character()) {
            this.onNameAdd();
        } else if (this.isPageChange()) {
            SoundManager.playOk();
            this.cursorPagedown();
        } else if (this.isOk()) {
            this.onNameOk();
        }
    };
    onNameAdd(): void {
        if (this._editWindow.add(this.character())) {
            SoundManager.playOk();
        } else {
            SoundManager.playBuzzer();
        }
    };
    onNameOk(): void {
        if (this._editWindow.name() === '') {
            if (this._editWindow.restoreDefault()) {
                SoundManager.playOk();
            } else {
                SoundManager.playBuzzer();
            }
        } else {
            SoundManager.playOk();
            this.callOkHandler();
        }
    };
}

//-----------------------------------------------------------------------------
// Window_ChoiceList
//
// The window used for the event command [Show Choices].

 class Window_ChoiceList extends Window_Command {
    constructor(messageWindow?: Window_Message) {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(messageWindow?: Window_Message|any): void {
        this._messageWindow = messageWindow;
        Window_Command.prototype.initialize.call(this, 0, 0);
        this.openness = 0;
        this.deactivate();
        this._background = 0;
    };
    _messageWindow: Window_Message;
    _background: number;

    start(): void {
        this.updatePlacement();
        this.updateBackground();
        this.refresh();
        this.selectDefault();
        this.open();
        this.activate();
    };
    selectDefault(): void {
        this.select($gameMessage.choiceDefaultType());
    };
    updatePlacement(): void {
        var positionType = $gameMessage.choicePositionType();
        var messageY = this._messageWindow.y;
        this.width = this.windowWidth();
        this.height = this.windowHeight();
        switch (positionType) {
        case 0:
            this.x = 0;
            break;
        case 1:
            this.x = (Graphics.boxWidth - this.width) / 2;
            break;
        case 2:
            this.x = Graphics.boxWidth - this.width;
            break;
        }
        if (messageY >= Graphics.boxHeight / 2) {
            this.y = messageY - this.height;
        } else {
            this.y = messageY + this._messageWindow.height;
        }
    };
    updateBackground(): void {
        this._background = $gameMessage.choiceBackground();
        this.setBackgroundType(this._background);
    };
    windowWidth(): number {
        var width = this.maxChoiceWidth() + this.padding * 2;
        return Math.min(width, Graphics.boxWidth);
    };
    numVisibleRows(): number {
        var messageY = this._messageWindow.y;
        var messageHeight = this._messageWindow.height;
        var centerY = Graphics.boxHeight / 2;
        var choices = $gameMessage.choices();
        var numLines = choices.length;
        var maxLines = 8;
        if (messageY < centerY && messageY + messageHeight > centerY) {
            maxLines = 4;
        }
        if (numLines > maxLines) {
            numLines = maxLines;
        }
        return numLines;
    };
    maxChoiceWidth(): number {
        var maxWidth = 96;
        var choices = $gameMessage.choices();
        for (var i = 0; i < choices.length; i++) {
            var choiceWidth = this.textWidthEx(choices[i]) + this.textPadding() * 2;
            if (maxWidth < choiceWidth) {
                maxWidth = choiceWidth;
            }
        }
        return maxWidth;
    };
    textWidthEx(text: string): number {
        return this.drawTextEx(text, 0, this.contents.height);
    };
    contentsHeight(): number {
        return this.maxItems() * this.itemHeight();
    };
    makeCommandList(): void {
        var choices = $gameMessage.choices();
        for (var i = 0; i < choices.length; i++) {
            this.addCommand(choices[i], 'choice');
        }
    };
    drawItem(index: number): void {
        var rect = this.itemRectForText(index);
        this.drawTextEx(this.commandName(index), rect.x, rect.y);
    };
    isCancelEnabled(): boolean {
        return $gameMessage.choiceCancelType() !== -1;
    };
    isOkTriggered(): boolean {
        return Input.isTriggered('ok');
    };
    callOkHandler(): void {
        $gameMessage.onChoice(this.index());
        this._messageWindow.terminateMessage();
        this.close();
    };
    callCancelHandler(): void {
        $gameMessage.onChoice($gameMessage.choiceCancelType());
        this._messageWindow.terminateMessage();
        this.close();
    };
}

//-----------------------------------------------------------------------------
// Window_NumberInput
//
// The window used for the event command [Input Number].

 class Window_NumberInput extends Window_Selectable {
    constructor(messageWindow?: Window_Message) {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(messageWindow?: Window_Message|any): void {
        this._messageWindow = messageWindow;
        Window_Selectable.prototype.initialize.call(this, 0, 0, 0, 0);
        this._number = 0;
        this._maxDigits = 1;
        this.openness = 0;
        this.createButtons();
        this.deactivate();
    };
    _messageWindow: Window_Message;
    _number: number;
    _maxDigits: number;
    _buttons: Sprite_Button[];

    start(): void {
        this._maxDigits = $gameMessage.numInputMaxDigits();
        this._number = $gameVariables.value($gameMessage.numInputVariableId());
        this._number = this._number.clamp(0, Math.pow(10, this._maxDigits) - 1);
        this.updatePlacement();
        this.placeButtons();
        this.updateButtonsVisiblity();
        this.createContents();
        this.refresh();
        this.open();
        this.activate();
        this.select(0);
    };
    updatePlacement(): void {
        var messageY = this._messageWindow.y;
        var spacing = 8;
        this.width = this.windowWidth();
        this.height = this.windowHeight();
        this.x = (Graphics.boxWidth - this.width) / 2;
        if (messageY >= Graphics.boxHeight / 2) {
            this.y = messageY - this.height - spacing;
        } else {
            this.y = messageY + this._messageWindow.height + spacing;
        }
    };
    windowWidth(): number {
        return this.maxCols() * this.itemWidth() + this.padding * 2;
    };
    windowHeight(): number {
        return this.fittingHeight(1);
    };
    maxCols(): number {
        return this._maxDigits;
    };
    maxItems(): number {
        return this._maxDigits;
    };
    spacing(): number {
        return 0;
    };
    itemWidth(): number {
        return 32;
    };
    createButtons(): void {
        var bitmap = ImageManager.loadSystem('ButtonSet');
        var buttonWidth = 48;
        var buttonHeight = 48;
        this._buttons = [];
        for (var i = 0; i < 3; i++) {
            var button = new Sprite_Button();
            var x = buttonWidth * [1, 2, 4][i];
            var w = buttonWidth * (i === 2 ? 2 : 1);
            button.bitmap = bitmap;
            button.setColdFrame(x, 0, w, buttonHeight);
            button.setHotFrame(x, buttonHeight, w, buttonHeight);
            button.visible = false;
            this._buttons.push(button);
            this.addChild(button);
        }
        this._buttons[0].setClickHandler(this.onButtonDown.bind(this));
        this._buttons[1].setClickHandler(this.onButtonUp.bind(this));
        this._buttons[2].setClickHandler(this.onButtonOk.bind(this));
    };
    placeButtons(): void {
        var numButtons = this._buttons.length;
        var spacing = 16;
        var totalWidth = -spacing;
        for (var i = 0; i < numButtons; i++) {
            totalWidth += this._buttons[i].width + spacing;
        }
        var x = (this.width - totalWidth) / 2;
        for (var j = 0; j < numButtons; j++) {
            var button = this._buttons[j];
            button.x = x;
            button.y = this.buttonY();
            x += button.width + spacing;
        }
    };
    updateButtonsVisiblity(): void {
        if (TouchInput.date > Input.date) {
            this.showButtons();
        } else {
            this.hideButtons();
        }
    };
    showButtons(): void {
        for (var i = 0; i < this._buttons.length; i++) {
            this._buttons[i].visible = true;
        }
    };
    hideButtons(): void {
        for (var i = 0; i < this._buttons.length; i++) {
            this._buttons[i].visible = false;
        }
    };
    buttonY(): number {
        var spacing = 8;
        if (this._messageWindow.y >= Graphics.boxHeight / 2) {
            return 0 - this._buttons[0].height - spacing;
        } else {
            return this.height + spacing;
        }
    };
    update(): void {
        Window_Selectable.prototype.update.call(this);
        this.processDigitChange();
    };
    processDigitChange(): void {
        if (this.isOpenAndActive()) {
            if (Input.isRepeated('up')) {
                this.changeDigit(true);
            } else if (Input.isRepeated('down')) {
                this.changeDigit(false);
            }
        }
    };
    changeDigit(up: boolean): void {
        var index = this.index();
        var place = Math.pow(10, this._maxDigits - 1 - index);
        var n = Math.floor(this._number / place) % 10;
        this._number -= n * place;
        if (up) {
            n = (n + 1) % 10;
        } else {
            n = (n + 9) % 10;
        }
        this._number += n * place;
        this.refresh();
        SoundManager.playCursor();
    };
    isTouchOkEnabled(): boolean {
        return false;
    };
    isOkEnabled(): boolean {
        return true;
    };
    isCancelEnabled(): boolean {
        return false;
    };
    isOkTriggered(): boolean {
        return Input.isTriggered('ok');
    };
    processOk(): void {
        SoundManager.playOk();
        $gameVariables.setValue($gameMessage.numInputVariableId(), this._number);
        this._messageWindow.terminateMessage();
        this.updateInputData();
        this.deactivate();
        this.close();
    };
    drawItem(index: number): void {
        var rect = this.itemRect(index);
        var align = 'center';
        var s = this._number.padZero(this._maxDigits);
        var c = s.slice(index, index + 1);
        this.resetTextColor();
        this.drawText(c, rect.x, rect.y, rect.width, align);
    };
    onButtonUp(): void {
        this.changeDigit(true);
    };
    onButtonDown(): void {
        this.changeDigit(false);
    };
    onButtonOk(): void {
        this.processOk();
        this.hideButtons();
    };
}

//-----------------------------------------------------------------------------
// Window_EventItem
//
// The window used for the event command [Select Item].

 class Window_EventItem extends Window_ItemList {
    constructor(messageWindow?: Window_Message){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(messageWindow?: Window_Message|any): void {
        this._messageWindow = messageWindow;
        var width = Graphics.boxWidth;
        var height = this.windowHeight();
        Window_ItemList.prototype.initialize.call(this, 0, 0, width, height);
        this.openness = 0;
        this.deactivate();
        this.setHandler('ok',     this.onOk.bind(this));
        this.setHandler('cancel', this.onCancel.bind(this));
    };
    _messageWindow: Window_Message;

    windowHeight(): number {
        return this.fittingHeight(this.numVisibleRows());
    };
    numVisibleRows(): number {
        return 4;
    };
    start(): void {
        this.refresh();
        this.updatePlacement();
        this.select(0);
        this.open();
        this.activate();
    };
    updatePlacement(): void {
        if (this._messageWindow.y >= Graphics.boxHeight / 2) {
            this.y = 0;
        } else {
            this.y = Graphics.boxHeight - this.height;
        }
    };
    includes(item: RPGMakerMV.DataAnyItem): boolean {
        var itypeId = $gameMessage.itemChoiceItypeId();
        return DataManager.isItem(item) && item.itypeId === itypeId;
    };
    isEnabled(item: RPGMakerMV.DataAnyItem): boolean {
        return true;
    };
    onOk(): void {
        var item = this.item();
        var itemId = item ? item.id : 0;
        $gameVariables.setValue($gameMessage.itemChoiceVariableId(), itemId);
        this._messageWindow.terminateMessage();
        this.close();
    };
    onCancel(): void {
        $gameVariables.setValue($gameMessage.itemChoiceVariableId(), 0);
        this._messageWindow.terminateMessage();
        this.close();
    };
}

//-----------------------------------------------------------------------------
// Window_Message
//
// The window for displaying text messages.

 class Window_Message extends Window_Base {
    constructor() {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(): void {
        var width = this.windowWidth();
        var height = this.windowHeight();
        var x = (Graphics.boxWidth - width) / 2;
        Window_Base.prototype.initialize.call(this, x, 0, width, height);
        this.openness = 0;
        this.initMembers();
        this.createSubWindows();
        this.updatePlacement();
    };
    initMembers(): void {
        this._imageReservationId = Utils.generateRuntimeId();
        this._background = 0;
        this._positionType = 2;
        this._waitCount = 0;
        this._faceBitmap = null;
        this._textState = null;
        this.clearFlags();
    };
    _imageReservationId:number;
    _background: number;
    _positionType: number;
    _waitCount: number;
    _faceBitmap: Bitmap;
    _textState: RPGMakerMV.TextState;

    subWindows(): Window_Base[]|any {
        return [this._goldWindow, this._choiceWindow,
                this._numberWindow, this._itemWindow];
    };
    createSubWindows(): void {
        this._goldWindow = new Window_Gold(0, 0);
        this._goldWindow.x = Graphics.boxWidth - this._goldWindow.width;
        this._goldWindow.openness = 0;
        this._choiceWindow = new Window_ChoiceList(this);
        this._numberWindow = new Window_NumberInput(this);
        this._itemWindow = new Window_EventItem(this);
    };
    _goldWindow: Window_Gold;
    _choiceWindow: Window_ChoiceList;
    _numberWindow: Window_NumberInput;
    _itemWindow: Window_EventItem;
    windowWidth(): number {
        return Graphics.boxWidth;
    };
    windowHeight(): number {
        return this.fittingHeight(this.numVisibleRows());
    };
    clearFlags(): void {
        this._showFast = false;
        this._lineShowFast = false;
        this._pauseSkip = false;
    };
    _showFast: boolean;
    _lineShowFast: boolean;
    _pauseSkip: boolean;
    numVisibleRows(): number {
        return 4;
    };
    update(): void {
        this.checkToNotClose();
        Window_Base.prototype.update.call(this);
        while (!this.isOpening() && !this.isClosing()) {
            if (this.updateWait()) {
                return;
            } else if (this.updateLoading()) {
                return;
            } else if (this.updateInput()) {
                return;
            } else if (this.updateMessage()) {
                return;
            } else if (this.canStart()) {
                this.startMessage();
            } else {
                this.startInput();
                return;
            }
        }
    };
    checkToNotClose(): void {
        if (this.isClosing() && this.isOpen()) {
            if (this.doesContinue()) {
                this.open();
            }
        }
    };
    canStart(): boolean {
        return $gameMessage.hasText() && !$gameMessage.scrollMode();
    };
    startMessage(): void {
        this._textState = {};
        this._textState.index = 0;
        this._textState.text = this.convertEscapeCharacters($gameMessage.allText());
        this.newPage(this._textState);
        this.updatePlacement();
        this.updateBackground();
        this.open();
    };
    updatePlacement(): void {
        this._positionType = $gameMessage.positionType();
        this.y = this._positionType * (Graphics.boxHeight - this.height) / 2;
        this._goldWindow.y = this.y > 0 ? 0 : Graphics.boxHeight - this._goldWindow.height;
    };
    updateBackground(): void {
        this._background = $gameMessage.background();
        this.setBackgroundType(this._background);
    };
    terminateMessage(): void {
        this.close();
        this._goldWindow.close();
        $gameMessage.clear();
    };
    updateWait(): boolean {
        if (this._waitCount > 0) {
            this._waitCount--;
            return true;
        } else {
            return false;
        }
    };
    updateLoading(): boolean {
        if (this._faceBitmap) {
            if (this._faceBitmap.isReady()) {
                this.drawMessageFace();
                this._faceBitmap = null;
                return false;
            } else {
                return true;
            }
        } else {
            return false;
        }
    };
    updateInput(): boolean {
        if (this.isAnySubWindowActive()) {
            return true;
        }
        if (this.pause) {
            if (this.isTriggered()) {
                Input.update();
                this.pause = false;
                if (!this._textState) {
                    this.terminateMessage();
                }
            }
            return true;
        }
        return false;
    };
    isAnySubWindowActive(): boolean {
        return (this._choiceWindow.active ||
                this._numberWindow.active ||
                this._itemWindow.active);
    };
    updateMessage(): boolean {
        if (this._textState) {
            while (!this.isEndOfText(this._textState)) {
                if (this.needsNewPage(this._textState)) {
                    this.newPage(this._textState);
                }
                this.updateShowFast();
                this.processCharacter(this._textState);
                if (!this._showFast && !this._lineShowFast) {
                    break;
                }
                if (this.pause || this._waitCount > 0) {
                    break;
                }
            }
            if (this.isEndOfText(this._textState)) {
                this.onEndOfText();
            }
            return true;
        } else {
            return false;
        }
    };
    onEndOfText(): void {
        if (!this.startInput()) {
            if (!this._pauseSkip) {
                this.startPause();
            } else {
                this.terminateMessage();
            }
        }
        this._textState = null;
    };
    startInput(): boolean {
        if ($gameMessage.isChoice()) {
            this._choiceWindow.start();
            return true;
        } else if ($gameMessage.isNumberInput()) {
            this._numberWindow.start();
            return true;
        } else if ($gameMessage.isItemChoice()) {
            this._itemWindow.start();
            return true;
        } else {
            return false;
        }
    };
    isTriggered(): boolean {
        return (Input.isRepeated('ok') || Input.isRepeated('cancel') ||
                TouchInput.isRepeated());
    };    
    doesContinue(): boolean {
        return ($gameMessage.hasText() && !$gameMessage.scrollMode() &&
                !this.areSettingsChanged());
    };
    areSettingsChanged(): boolean {
        return (this._background !== $gameMessage.background() ||
                this._positionType !== $gameMessage.positionType());
    };
    updateShowFast(): void {
        if (this.isTriggered()) {
            this._showFast = true;
        }
    };
    newPage(textState: RPGMakerMV.TextState): void {
        this.contents.clear();
        this.resetFontSettings();
        this.clearFlags();
        this.loadMessageFace();
        textState.x = this.newLineX();
        textState.y = 0;
        textState.left = this.newLineX();
        textState.height = this.calcTextHeight(textState, false);
    };
    loadMessageFace(): void {
        this._faceBitmap = ImageManager.reserveFace($gameMessage.faceName(), 0, this._imageReservationId);
    };
    drawMessageFace(): void {
        this.drawFace($gameMessage.faceName(), $gameMessage.faceIndex(), 0, 0);
        ImageManager.releaseReservation(this._imageReservationId);
    };
    newLineX(): number {
        return $gameMessage.faceName() === '' ? 0 : 168;
    };
    processNewLine(textState: RPGMakerMV.TextState): void {
        this._lineShowFast = false;
        Window_Base.prototype.processNewLine.call(this, textState);
        if (this.needsNewPage(textState)) {
            this.startPause();
        }
    };
    processNewPage(textState: RPGMakerMV.TextState): void {
        Window_Base.prototype.processNewPage.call(this, textState);
        if (textState.text[textState.index] === '\n') {
            textState.index++;
        }
        textState.y = this.contents.height;
        this.startPause();
    };
    isEndOfText(textState: RPGMakerMV.TextState): boolean {
        return textState.index >= textState.text.length;
    };
    needsNewPage(textState: RPGMakerMV.TextState): boolean {
        return (!this.isEndOfText(textState) &&
                textState.y + textState.height > this.contents.height);
    };
    processEscapeCharacter(code: string, textState: RPGMakerMV.TextState): void {
        switch (code) {
        case '$':
            this._goldWindow.open();
            break;
        case '.':
            this.startWait(15);
            break;
        case '|':
            this.startWait(60);
            break;
        case '!':
            this.startPause();
            break;
        case '>':
            this._lineShowFast = true;
            break;
        case '<':
            this._lineShowFast = false;
            break;
        case '^':
            this._pauseSkip = true;
            break;
        default:
            Window_Base.prototype.processEscapeCharacter.call(this, code, textState);
            break;
        }
    };
    startWait(count: number): void {
        this._waitCount = count;
    };
    startPause(): void {
        this.startWait(10);
        this.pause = true;
    };
}

//-----------------------------------------------------------------------------
// Window_ScrollText
//
// The window for displaying scrolling text. No frame is displayed, but it
// is handled as a window for convenience.

 class Window_ScrollText extends Window_Base {
    constructor() {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(): void {
        var width = Graphics.boxWidth;
        var height = Graphics.boxHeight;
        Window_Base.prototype.initialize.call(this, 0, 0, width, height);
        this.opacity = 0;
        this.hide();
        this._text = '';
        this._allTextHeight = 0;
    };
    _text: string;
    _allTextHeight: number;

    update(): void {
        Window_Base.prototype.update.call(this);
        if ($gameMessage.scrollMode()) {
            if (this._text) {
                this.updateMessage();
            }
            if (!this._text && $gameMessage.hasText()) {
                this.startMessage();
            }
        }
    };
    startMessage(): void {
        this._text = $gameMessage.allText();
        this.refresh();
        this.show();
    };
    refresh(): void {
        var textState:any = { index: 0 };
        textState.text = this.convertEscapeCharacters(this._text);
        this.resetFontSettings();
        this._allTextHeight = this.calcTextHeight(textState, true);
        this.createContents();
        this.origin.y = -this.height;
        this.drawTextEx(this._text, this.textPadding(), 1);
    };
    contentsHeight(): number {
        return Math.max(this._allTextHeight, 1);
    };
    updateMessage(): void {
        this.origin.y += this.scrollSpeed();
        if (this.origin.y >= this.contents.height) {
            this.terminateMessage();
        }
    };
    scrollSpeed(): number {
        var speed = $gameMessage.scrollSpeed() / 2;
        if (this.isFastForward()) {
            speed *= this.fastForwardRate();
        }
        return speed;
    };
    isFastForward(): boolean {
        if ($gameMessage.scrollNoFast()) {
            return false;
        } else {
            return (Input.isPressed('ok') || Input.isPressed('shift') ||
                    TouchInput.isPressed());
        }
    };
    fastForwardRate(): number {
        return 3;
    };
    terminateMessage(): void {
        this._text = null;
        $gameMessage.clear();
        this.hide();
    };
}

//-----------------------------------------------------------------------------
// Window_MapName
//
// The window for displaying the map name on the map screen.

 class Window_MapName extends Window_Base {
    constructor(){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(): void {
        var wight = this.windowWidth();
        var height = this.windowHeight();
        Window_Base.prototype.initialize.call(this, 0, 0, wight, height);
        this.opacity = 0;
        this.contentsOpacity = 0;
        this._showCount = 0;
        this.refresh();
    };
    _showCount: number;

    windowWidth(): number {
        return 360;
    };
    windowHeight(): number {
        return this.fittingHeight(1);
    };
    update(): void {
        Window_Base.prototype.update.call(this);
        if (this._showCount > 0 && $gameMap.isNameDisplayEnabled()) {
            this.updateFadeIn();
            this._showCount--;
        } else {
            this.updateFadeOut();
        }
    };
    updateFadeIn(): void {
        this.contentsOpacity += 16;
    };
    updateFadeOut(): void {
        this.contentsOpacity -= 16;
    };
    open(): void {
        this.refresh();
        this._showCount = 150;
    };
    close(): void {
        this._showCount = 0;
    };
    refresh(): void {
        this.contents.clear();
        if ($gameMap.displayName()) {
            var width = this.contentsWidth();
            this.drawBackground(0, 0, width, this.lineHeight());
            this.drawText($gameMap.displayName(), 0, 0, width, 'center');
        }
    };
    drawBackground(x: number, y: number, width: number, height: number): void {
        var color1 = this.dimColor1();
        var color2 = this.dimColor2();
        this.contents.gradientFillRect(x, y, width / 2, height, color2, color1);
        this.contents.gradientFillRect(x + width / 2, y, width / 2, height, color1, color2);
    };
}

//-----------------------------------------------------------------------------
// Window_BattleLog
//
// The window for displaying battle progress. No frame is displayed, but it is
// handled as a window for convenience.

 class Window_BattleLog extends Window_Selectable {
    constructor() {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(): void {
        var width = this.windowWidth();
        var height = this.windowHeight();
        Window_Selectable.prototype.initialize.call(this, 0, 0, width, height);
        this.opacity = 0;
        this._lines = [];
        this._methods = [];
        this._waitCount = 0;
        this._waitMode = '';
        this._baseLineStack = [];
        this._spriteset = null;
        this.createBackBitmap();
        this.createBackSprite();
        this.refresh();
    };
    _lines: string[];
    _methods: { name: string, params: any[] }[];
    _waitCount: number;
    _waitMode: string;
    _baseLineStack: number[];
    _spriteset: Spriteset_Battle;

    setSpriteset(spriteset: Spriteset_Battle): void {
        this._spriteset = spriteset;
    };
    windowWidth(): number {
        return Graphics.boxWidth;
    };
    windowHeight(): number {
        return this.fittingHeight(this.maxLines());
    };
    maxLines(): number {
        return 10;
    };
    createBackBitmap(): void {
        this._backBitmap = new Bitmap(this.width, this.height);
    };
    _backBitmap: Bitmap;
    createBackSprite(): void {
        this._backSprite = new Sprite();
        this._backSprite.bitmap = this._backBitmap;
        this._backSprite.y = this.y;
        this.addChildToBack(this._backSprite);
    };
    _backSprite: Sprite;
    numLines(): number {
        return this._lines.length;
    };
    messageSpeed(): number {
        return 16;
    };
    isBusy(): boolean|string {
        return this._waitCount > 0 || this._waitMode || this._methods.length > 0;
    };
    update(): void{
        if (!this.updateWait()) {
            this.callNextMethod();
        }
    };
    updateWait(): number|any {
        return this.updateWaitCount() || this.updateWaitMode();
    };
    updateWaitCount(): boolean {
        if (this._waitCount > 0) {
            this._waitCount -= this.isFastForward() ? 3 : 1;
            if (this._waitCount < 0) {
                this._waitCount = 0;
            }
            return true;
        }
        return false;
    };
    updateWaitMode(): number|any {
        var waiting = false;
        switch (this._waitMode) {
        case 'effect':
            waiting = this._spriteset.isEffecting();
            break;
        case 'movement':
            waiting = this._spriteset.isAnyoneMoving();
            break;
        }
        if (!waiting) {
            this._waitMode = '';
        }
        return waiting;
    };
    setWaitMode(waitMode: string): void {
        this._waitMode = waitMode;
    };
    callNextMethod(): void {
        if (this._methods.length > 0) {
            var method = this._methods.shift();
            if (method.name && this[method.name]) {
                this[method.name].apply(this, method.params);
            } else {
                throw new Error('Method not found: ' + method.name);
            }
        }
    };
    isFastForward(): boolean {
        return (Input.isLongPressed('ok') || Input.isPressed('shift') ||
                TouchInput.isLongPressed());
    };
    push(methodName: string, ...args: any[]): void {
        var methodArgs = Array.prototype.slice.call(arguments, 1);
        this._methods.push({ name: methodName, params: methodArgs });
    };
    clear(): void {
        this._lines = [];
        this._baseLineStack = [];
        this.refresh();
    };
    wait(): void {
        this._waitCount = this.messageSpeed();
    };
    waitForEffect(): void {
        this.setWaitMode('effect');
    };
    waitForMovement(): void {
        this.setWaitMode('movement');
    };
    addText(text: string): void {
        this._lines.push(text);
        this.refresh();
        this.wait();
    };
    pushBaseLine(): void {
        this._baseLineStack.push(this._lines.length);
    };
    popBaseLine(): void {
        var baseLine = this._baseLineStack.pop();
        while (this._lines.length > baseLine) {
            this._lines.pop();
        }
    };
    waitForNewLine(): void {
        var baseLine = 0;
        if (this._baseLineStack.length > 0) {
            baseLine = this._baseLineStack[this._baseLineStack.length - 1];
        }
        if (this._lines.length > baseLine) {
            this.wait();
        }
    };
    popupDamage(target: Game_Battler): void {
        target.startDamagePopup();
    };
    performActionStart(subject: Game_Battler, action: Game_Action): void {
        subject.performActionStart(action);
    };
    performAction(subject: Game_Battler, action: Game_Action): void {
        subject.performAction(action);
    };
    performActionEnd(subject: Game_Battler): void {
        subject.performActionEnd();
    };
    performDamage(target: Game_Battler): void{
        target.performDamage();
    };
    performMiss(target: Game_Battler): void {
        target.performMiss();
    };
    performRecovery(target: Game_Battler): void {
        target.performRecovery();
    };
    performEvasion(target: Game_Battler): void {
        target.performEvasion();
    };
    performMagicEvasion(target: Game_Battler): void {
        target.performMagicEvasion();
    };
    performCounter(target: Game_Battler): void {
        target.performCounter();
    };
    performReflection(target: Game_Battler): void {
        target.performReflection();
    };
    performSubstitute(substitute: Game_Battler, target: Game_Battler): void {
        substitute.performSubstitute(target);
    };
    performCollapse(target: Game_Battler): void {
        target.performCollapse();
    };
    showAnimation(subject: Game_Battler, targets: Game_Battler[], animationId: number): void {
        if (animationId < 0) {
            this.showAttackAnimation(subject, targets);
        } else {
            this.showNormalAnimation(targets, animationId);
        }
    };
    showAttackAnimation(subject: Game_Battler, targets: Game_Battler[]): void {
        if (subject.isActor()) {
            this.showActorAttackAnimation(subject, targets);
        } else {
            this.showEnemyAttackAnimation(subject, targets);
        }
    };
    showActorAttackAnimation(subject: Game_Battler|any, targets: Game_Battler[]): void {
        this.showNormalAnimation(targets, subject.attackAnimationId1(), false);
        this.showNormalAnimation(targets, subject.attackAnimationId2(), true);
    };
    showEnemyAttackAnimation(subject: Game_Battler, targets: Game_Battler[]): void {
        SoundManager.playEnemyAttack();
    };
    showNormalAnimation(targets: Game_Battler[], animationId: number, mirror?: boolean): void {
        var animation = $dataAnimations[animationId];
        if (animation) {
            var delay = this.animationBaseDelay();
            var nextDelay = this.animationNextDelay();
            targets.forEach(function(target) {
                target.startAnimation(animationId, mirror, delay);
                delay += nextDelay;
            });
        }
    };
    animationBaseDelay(): number {
        return 8;
    };    
    animationNextDelay(): number {
        return 12;
    };
    refresh(): void {
        this.drawBackground();
        this.contents.clear();
        for (var i = 0; i < this._lines.length; i++) {
            this.drawLineText(i);
        }
    };
    drawBackground(): void {
        var rect = this.backRect();
        var color = this.backColor();
        this._backBitmap.clear();
        this._backBitmap.paintOpacity = this.backPaintOpacity();
        this._backBitmap.fillRect(rect.x, rect.y, rect.width, rect.height, color);
        this._backBitmap.paintOpacity = 255;
    };
    backRect(): { x: number, y: number, width: number, height: number } {
        return {
            x: 0,
            y: this.padding,
            width: this.width,
            height: this.numLines() * this.lineHeight()
        };
    };
    backColor(): string {
        return '#000000';
    };
    backPaintOpacity(): number {
        return 64;
    };
    drawLineText(index: number): void {
        var rect = this.itemRectForText(index);
        this.contents.clearRect(rect.x, rect.y, rect.width, rect.height);
        this.drawTextEx(this._lines[index], rect.x, rect.y, rect.width);
    };
    startTurn(): void {
        this.push('wait');
    };
    startAction(subject: Game_Battler, action: Game_Action, targets: Game_Battler[]): void {
        var item = action.item();
        this.push('performActionStart', subject, action);
        this.push('waitForMovement');
        this.push('performAction', subject, action);
        this.push('showAnimation', subject, targets.clone(), item.animationId);
        this.displayAction(subject, item);
    };
    endAction(subject: Game_Battler): void {
        this.push('waitForNewLine');
        this.push('clear');
        this.push('performActionEnd', subject);
    };
    displayCurrentState(subject: Game_Battler|any): void {
        var stateText = subject.mostImportantStateText();
        if (stateText) {
            this.push('addText', subject.name() + stateText);
            this.push('wait');
            this.push('clear');
        }
    };
    displayRegeneration(subject: Game_Battler): void {
        this.push('popupDamage', subject);
    };
    displayAction(subject: Game_Battler|any, item: RPGMakerMV.DataAnyItem | RPGMakerMV.DataSkill|any): void {
        var numMethods = this._methods.length;
        if (DataManager.isSkill(item)) {
            if (item.message1) {
                this.push('addText', subject.name() + item.message1.format(item.name));
            }
            if (item.message2) {
                this.push('addText', item.message2.format(item.name));
            }
        } else {
            this.push('addText', TextManager.useItem.format(subject.name(), item.name));
        }
        if (this._methods.length === numMethods) {
            this.push('wait');
        }
    };
    displayCounter(target: Game_Battler|any): void {
        this.push('performCounter', target);
        this.push('addText', TextManager.counterAttack.format(target.name()));
    };
    displayReflection(target: Game_Battler|any): void {
        this.push('performReflection', target);
        this.push('addText', TextManager.magicReflection.format(target.name()));
    };
    displaySubstitute(substitute: Game_Battler|any, target: Game_Battler|any): void {
        var substName = substitute.name();
        this.push('performSubstitute', substitute, target);
        this.push('addText', TextManager.substitute.format(substName, target.name()));
    };
    displayActionResults(subject: Game_Battler, target: Game_Battler): void {
        if (target.result().used) {
            this.push('pushBaseLine');
            this.displayCritical(target);
            this.push('popupDamage', target);
            this.push('popupDamage', subject);
            this.displayDamage(target);
            this.displayAffectedStatus(target);
            this.displayFailure(target);
            this.push('waitForNewLine');
            this.push('popBaseLine');
        }
    };
    displayFailure(target: Game_Battler|any): void {
        if (target.result().isHit() && !target.result().success) {
            this.push('addText', TextManager.actionFailure.format(target.name()));
        }
    };
    displayCritical(target: Game_Battler): void {
        if (target.result().critical) {
            if (target.isActor()) {
                this.push('addText', TextManager.criticalToActor);
            } else {
                this.push('addText', TextManager.criticalToEnemy);
            }
        }
    };
    displayDamage(target: Game_Battler): void {
        if (target.result().missed) {
            this.displayMiss(target);
        } else if (target.result().evaded) {
            this.displayEvasion(target);
        } else {
            this.displayHpDamage(target);
            this.displayMpDamage(target);
            this.displayTpDamage(target);
        }
    };
    displayMiss(target: Game_Battler|any): void {
        var fmt;
        if (target.result().physical) {
            fmt = target.isActor() ? TextManager.actorNoHit : TextManager.enemyNoHit;
            this.push('performMiss', target);
        } else {
            fmt = TextManager.actionFailure;
        }
        this.push('addText', fmt.format(target.name()));
    };
    displayEvasion(target: Game_Battler|any): void {
        var fmt;
        if (target.result().physical) {
            fmt = TextManager.evasion;
            this.push('performEvasion', target);
        } else {
            fmt = TextManager.magicEvasion;
            this.push('performMagicEvasion', target);
        }
        this.push('addText', fmt.format(target.name()));
    };
    displayHpDamage(target: Game_Battler): void {
        if (target.result().hpAffected) {
            if (target.result().hpDamage > 0 && !target.result().drain) {
                this.push('performDamage', target);
            }
            if (target.result().hpDamage < 0) {
                this.push('performRecovery', target);
            }
            this.push('addText', this.makeHpDamageText(target));
        }
    };
    displayMpDamage(target: Game_Battler): void {
        if (target.isAlive() && target.result().mpDamage !== 0) {
            if (target.result().mpDamage < 0) {
                this.push('performRecovery', target);
            }
            this.push('addText', this.makeMpDamageText(target));
        }
    };
    displayTpDamage(target: Game_Battler): void {
        if (target.isAlive() && target.result().tpDamage !== 0) {
            if (target.result().tpDamage < 0) {
                this.push('performRecovery', target);
            }
            this.push('addText', this.makeTpDamageText(target));
        }
    };
    displayAffectedStatus(target: Game_Battler, obj?:any): void {
        if (target.result().isStatusAffected()) {
            this.push('pushBaseLine');
            this.displayChangedStates(target);
            this.displayChangedBuffs(target);
            this.push('waitForNewLine');
            this.push('popBaseLine');
        }
    };
    displayAutoAffectedStatus(target: Game_Battler): void {
        if (target.result().isStatusAffected()) {
            this.displayAffectedStatus(target, null);
            this.push('clear');
        }
    };
    displayChangedStates(target: Game_Battler): void {
        this.displayAddedStates(target);
        this.displayRemovedStates(target);
    };
    displayAddedStates(target: Game_Battler|any): void {
        target.result().addedStateObjects().forEach( (state: { message1: any; message2: any; id: any; }) => {
            var stateMsg = target.isActor() ? state.message1 : state.message2;
            if (state.id === target.deathStateId()) {
                this.push('performCollapse', target);
            }
            if (stateMsg) {
                this.push('popBaseLine');
                this.push('pushBaseLine');
                this.push('addText', target.name() + stateMsg);
                this.push('waitForEffect');
            }
        }, this);
    };
    displayRemovedStates(target: Game_Battler|any): void {
        target.result().removedStateObjects().forEach( (state: { message4: any; }) => {
            if (state.message4) {
                this.push('popBaseLine');
                this.push('pushBaseLine');
                this.push('addText', target.name() + state.message4);
            }
        }, this);
    };
    displayChangedBuffs(target: Game_Battler): void {
        var result = target.result();
        this.displayBuffs(target, result.addedBuffs, TextManager.buffAdd);
        this.displayBuffs(target, result.addedDebuffs, TextManager.debuffAdd);
        this.displayBuffs(target, result.removedBuffs, TextManager.buffRemove);
    };
    displayBuffs(target: Game_Battler|any, buffs: number[], fmt: string): void {
        buffs.forEach(paramId => {
            this.push('popBaseLine');
            this.push('pushBaseLine');
            this.push('addText', fmt.format(target.name(), TextManager.param(paramId)));
        }, this);
    };
    makeHpDamageText(target: Game_Battler|any): string {
        var result = target.result();
        var damage = result.hpDamage;
        var isActor = target.isActor();
        var fmt;
        if (damage > 0 && result.drain) {
            fmt = isActor ? TextManager.actorDrain : TextManager.enemyDrain;
            return fmt.format(target.name(), TextManager.hp, damage);
        } else if (damage > 0) {
            fmt = isActor ? TextManager.actorDamage : TextManager.enemyDamage;
            return fmt.format(target.name(), damage);
        } else if (damage < 0) {
            fmt = isActor ? TextManager.actorRecovery : TextManager.enemyRecovery;
            return fmt.format(target.name(), TextManager.hp, -damage);
        } else {
            fmt = isActor ? TextManager.actorNoDamage : TextManager.enemyNoDamage;
            return fmt.format(target.name());
        }
    };
    makeMpDamageText(target: Game_Battler|any): string {
        var result = target.result();
        var damage = result.mpDamage;
        var isActor = target.isActor();
        var fmt;
        if (damage > 0 && result.drain) {
            fmt = isActor ? TextManager.actorDrain : TextManager.enemyDrain;
            return fmt.format(target.name(), TextManager.mp, damage);
        } else if (damage > 0) {
            fmt = isActor ? TextManager.actorLoss : TextManager.enemyLoss;
            return fmt.format(target.name(), TextManager.mp, damage);
        } else if (damage < 0) {
            fmt = isActor ? TextManager.actorRecovery : TextManager.enemyRecovery;
            return fmt.format(target.name(), TextManager.mp, -damage);
        } else {
            return '';
        }
    };
    makeTpDamageText(target: Game_Battler|any): string {
        var result = target.result();
        var damage = result.tpDamage;
        var isActor = target.isActor();
        var fmt;
        if (damage > 0) {
            fmt = isActor ? TextManager.actorLoss : TextManager.enemyLoss;
            return fmt.format(target.name(), TextManager.tp, damage);
        } else if (damage < 0) {
            fmt = isActor ? TextManager.actorGain : TextManager.enemyGain;
            return fmt.format(target.name(), TextManager.tp, -damage);
        } else {
            return '';
        }
    };
}

//-----------------------------------------------------------------------------
// Window_PartyCommand
//
// The window for selecting whether to fight or escape on the battle screen.

 class Window_PartyCommand extends Window_Command {
    constructor(){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(): void {
        var y = Graphics.boxHeight - this.windowHeight();
        Window_Command.prototype.initialize.call(this, 0, y);
        this.openness = 0;
        this.deactivate();
    };
    windowWidth(): number {
        return 192;
    };
    numVisibleRows(): number {
        return 4;
    };
    makeCommandList(): void {
        this.addCommand(TextManager.fight,  'fight');
        this.addCommand(TextManager.escape, 'escape', BattleManager.canEscape());
    };
    setup(): void {
        this.clearCommandList();
        this.makeCommandList();
        this.refresh();
        this.select(0);
        this.activate();
        this.open();
    };
}

//-----------------------------------------------------------------------------
// Window_ActorCommand
//
// The window for selecting an actor's action on the battle screen.

 class Window_ActorCommand extends Window_Command {
    constructor(){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(): void {
        var y = Graphics.boxHeight - this.windowHeight();
        Window_Command.prototype.initialize.call(this, 0, y);
        this.openness = 0;
        this.deactivate();
        this._actor = null;
    };
    _actor: Game_Actor;

    windowWidth(): number {
        return 192;
    };
    numVisibleRows(): number {
        return 4;
    };
    makeCommandList(): void {
        if (this._actor) {
            this.addAttackCommand();
            this.addSkillCommands();
            this.addGuardCommand();
            this.addItemCommand();
        }
    };
    addAttackCommand(): void {
        this.addCommand(TextManager.attack, 'attack', this._actor.canAttack());
    };
    addSkillCommands(): void {
        var skillTypes = this._actor.addedSkillTypes();
        skillTypes.sort(function(a, b) {
            return a - b;
        });
        skillTypes.forEach(stypeId => {
            var name = $dataSystem.skillTypes[stypeId];
            this.addCommand(name, 'skill', true, stypeId);
        }, this);
    };
    addGuardCommand(): void {
        this.addCommand(TextManager.guard, 'guard', this._actor.canGuard());
    };
    addItemCommand(): void {
        this.addCommand(TextManager.item, 'item');
    };
    setup(actor: Game_Actor): void {
        this._actor = actor;
        this.clearCommandList();
        this.makeCommandList();
        this.refresh();
        this.selectLast();
        this.activate();
        this.open();
    };
    processOk(): void {
        if (this._actor) {
            if (ConfigManager.commandRemember) {
                this._actor.setLastCommandSymbol(this.currentSymbol());
            } else {
                this._actor.setLastCommandSymbol('');
            }
        }
        Window_Command.prototype.processOk.call(this);
    };
    selectLast(): void {
        this.select(0);
        if (this._actor && ConfigManager.commandRemember) {
            var symbol = this._actor.lastCommandSymbol();
            this.selectSymbol(symbol);
            if (symbol === 'skill') {
                var skill = this._actor.lastBattleSkill();
                if (skill) {
                    this.selectExt(skill.stypeId);
                }
            }
        }
    };
}

//-----------------------------------------------------------------------------
// Window_BattleStatus
//
// The window for displaying the status of party members on the battle screen.

 class Window_BattleStatus extends Window_Selectable {
    constructor() {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(): void {
        var width = this.windowWidth();
        var height = this.windowHeight();
        var x = Graphics.boxWidth - width;
        var y = Graphics.boxHeight - height;
        Window_Selectable.prototype.initialize.call(this, x, y, width, height);
        this.refresh();
        this.openness = 0;
    };
    windowWidth(): number {
        return Graphics.boxWidth - 192;
    };
    windowHeight(): number {
        return this.fittingHeight(this.numVisibleRows());
    };
    numVisibleRows(): number {
        return 4;
    };
    maxItems(): number {
        return $gameParty.battleMembers().length;
    };
    refresh(): void {
        this.contents.clear();
        this.drawAllItems();
    };
    drawItem(index: number): void {
        var actor = $gameParty.battleMembers()[index];
        this.drawBasicArea(this.basicAreaRect(index), actor);
        this.drawGaugeArea(this.gaugeAreaRect(index), actor);
    };
    basicAreaRect(index: number): void|any {
        var rect = this.itemRectForText(index);
        rect.width -= this.gaugeAreaWidth() + 15;
        return rect;
    };
    gaugeAreaRect(index: number): void|any {
        var rect = this.itemRectForText(index);
        rect.x += rect.width - this.gaugeAreaWidth();
        rect.width = this.gaugeAreaWidth();
        return rect;
    };
    gaugeAreaWidth(): number {
        return 330;
    };
    drawBasicArea(rect: { x: number, y: number, width: number, height: number }, actor: Game_Actor): void {
        this.drawActorName(actor, rect.x + 0, rect.y, 150);
        this.drawActorIcons(actor, rect.x + 156, rect.y, rect.width - 156);
    };
    drawGaugeArea(rect: { x: number, y: number, width: number, height: number }, actor: Game_Actor): void {
        if ($dataSystem.optDisplayTp) {
            this.drawGaugeAreaWithTp(rect, actor);
        } else {
            this.drawGaugeAreaWithoutTp(rect, actor);
        }
    };
    drawGaugeAreaWithTp(rect: { x: number, y: number, width: number, height: number }, actor: Game_Actor): void {
        this.drawActorHp(actor, rect.x + 0, rect.y, 108);
        this.drawActorMp(actor, rect.x + 123, rect.y, 96);
        this.drawActorTp(actor, rect.x + 234, rect.y, 96);
    };
    drawGaugeAreaWithoutTp(rect: { x: number, y: number, width: number, height: number }, actor: Game_Actor): void {
        this.drawActorHp(actor, rect.x + 0, rect.y, 201);
        this.drawActorMp(actor, rect.x + 216,  rect.y, 114);
    };
}

//-----------------------------------------------------------------------------
// Window_BattleActor
//
// The window for selecting a target actor on the battle screen.

 class Window_BattleActor extends Window_BattleStatus {
    constructor(x?: number, y?: number) {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number): void {
        Window_BattleStatus.prototype.initialize.call(this);
        this.x = x;
        this.y = y;
        this.openness = 255;
        this.hide();
    };
    show(): void {
        this.select(0);
        Window_BattleStatus.prototype.show.call(this);
    };
    hide(): void {
        Window_BattleStatus.prototype.hide.call(this);
        $gameParty.select(null);
    };
    select(index: number): void {
        Window_BattleStatus.prototype.select.call(this, index);
        $gameParty.select(this.actor());
    };
    actor(): Game_Actor {
        return $gameParty.members()[this.index()];
    };
}

//-----------------------------------------------------------------------------
// Window_BattleEnemy
//
// The window for selecting a target enemy on the battle screen.

 class Window_BattleEnemy extends Window_Selectable {
    constructor(x?: number, y?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number): void {
        this._enemies = [];
        var width = this.windowWidth();
        var height = this.windowHeight();
        Window_Selectable.prototype.initialize.call(this, x, y, width, height);
        this.refresh();
        this.hide();
    };
    _enemies: Game_Enemy[];

    windowWidth(): number {
        return Graphics.boxWidth - 192;
    };
    windowHeight(): number {
        return this.fittingHeight(this.numVisibleRows());
    };
    numVisibleRows(): number {
        return 4;
    };
    maxCols(): number {
        return 2;
    };
    maxItems(): number {
        return this._enemies.length;
    };
    enemy(): Game_Enemy {
        return this._enemies[this.index()];
    };
    enemyIndex(): number {
        var enemy = this.enemy();
        return enemy ? enemy.index() : -1;
    };
    drawItem(index: number): void {
        this.resetTextColor();
        var name = this._enemies[index].name();
        var rect = this.itemRectForText(index);
        this.drawText(name, rect.x, rect.y, rect.width);
    };
    show(): void {
        this.refresh();
        this.select(0);
        Window_Selectable.prototype.show.call(this);
    };
    hide(): void {
        Window_Selectable.prototype.hide.call(this);
        $gameTroop.select(null);
    };
    refresh(): void {
        this._enemies = $gameTroop.aliveMembers();
        Window_Selectable.prototype.refresh.call(this);
    };
    select(index: number): void {
        Window_Selectable.prototype.select.call(this, index);
        $gameTroop.select(this.enemy());
    };
}

//-----------------------------------------------------------------------------
// Window_BattleSkill
//
// The window for selecting a skill to use on the battle screen.

 class Window_BattleSkill extends Window_SkillList {
    constructor(x?: number, y?: number, width?: number, height?: number) {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, width?: number, height?: number): void{
        Window_SkillList.prototype.initialize.call(this, x, y, width, height);
        this.hide();
    };
    show(): void {
        this.selectLast();
        this.showHelpWindow();
        Window_SkillList.prototype.show.call(this);
    };
    hide(): void {
        this.hideHelpWindow();
        Window_SkillList.prototype.hide.call(this);
    };
}

//-----------------------------------------------------------------------------
// Window_BattleItem
//
// The window for selecting an item to use on the battle screen.

 class Window_BattleItem extends Window_ItemList {
    constructor(x?: number, y?: number, width?: number, height?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, width?: number, height?: number): void {
        Window_ItemList.prototype.initialize.call(this, x, y, width, height);
        this.hide();
    };
    includes(item: RPGMakerMV.DataAnyItem): boolean {
        return $gameParty.canUse(item);
    };
    show(): void {
        this.selectLast();
        this.showHelpWindow();
        Window_ItemList.prototype.show.call(this);
    };
    hide(): void {
        this.hideHelpWindow();
        Window_ItemList.prototype.hide.call(this);
    };
}

//-----------------------------------------------------------------------------
// Window_TitleCommand
//
// The window for selecting New Game/Continue on the title screen.

 class Window_TitleCommand extends Window_Command {
    constructor() {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(): void{
        Window_Command.prototype.initialize.call(this, 0, 0);
        this.updatePlacement();
        this.openness = 0;
        this.selectLast();
    };

    static _lastCommandSymbol: string = null;
    static initCommandPosition(): void{
        this._lastCommandSymbol = null;
    };

    windowWidth(): number {
        return 240;
    };
    updatePlacement(): void {
        this.x = (Graphics.boxWidth - this.width) / 2;
        this.y = Graphics.boxHeight - this.height - 96;
    };
    makeCommandList(): void {
        this.addCommand(TextManager.newGame,   'newGame');
        this.addCommand(TextManager.continue_, 'continue', this.isContinueEnabled());
        this.addCommand(TextManager.options,   'options');
    };
    isContinueEnabled(): boolean {
        return DataManager.isAnySavefileExists();
    };
    processOk(): void {
        Window_TitleCommand._lastCommandSymbol = this.currentSymbol();
        Window_Command.prototype.processOk.call(this);
    };
    selectLast(): void {
        if (Window_TitleCommand._lastCommandSymbol) {
            this.selectSymbol(Window_TitleCommand._lastCommandSymbol);
        } else if (this.isContinueEnabled()) {
            this.selectSymbol('continue');
        }
    };
}

//-----------------------------------------------------------------------------
// Window_GameEnd
//
// The window for selecting "Go to Title" on the game end screen.

 class Window_GameEnd extends Window_Command {
    constructor() {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(): void {
        Window_Command.prototype.initialize.call(this, 0, 0);
        this.updatePlacement();
        this.openness = 0;
        this.open();
    };
    windowWidth(): number {
        return 240;
    };
    updatePlacement(): void {
        this.x = (Graphics.boxWidth - this.width) / 2;
        this.y = (Graphics.boxHeight - this.height) / 2;
    };
    makeCommandList(): void {
        this.addCommand(TextManager.toTitle, 'toTitle');
        this.addCommand(TextManager.cancel,  'cancel');
    };
}

//-----------------------------------------------------------------------------
// Window_DebugRange
//
// The window for selecting a block of switches/variables on the debug screen.

 class Window_DebugRange extends Window_Selectable {
    constructor(x?: number, y?: number){
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number): void {
        this._maxSwitches = Math.ceil(($dataSystem.switches.length - 1) / 10);
        this._maxVariables = Math.ceil(($dataSystem.variables.length - 1) / 10);
        var width = this.windowWidth();
        var height = this.windowHeight();
        Window_Selectable.prototype.initialize.call(this, x, y, width, height);
        this.refresh();
        this.setTopRow(Window_DebugRange.lastTopRow);
        this.select(Window_DebugRange.lastIndex);
        this.activate();
    };

    static lastTopRow: number = 0;
    static lastIndex: number = 0;
    _maxSwitches: number;
    _maxVariables: number;

    windowWidth(): number {
        return 246;
    };
    windowHeight(): number {
        return Graphics.boxHeight;
    };
    maxItems(): number {
        return this._maxSwitches + this._maxVariables;
    };
    update(): void {
        Window_Selectable.prototype.update.call(this);
        if (this._editWindow) {
            this._editWindow.setMode(this.mode());
            this._editWindow.setTopId(this.topId());
        }
    };
    mode(): string {
        return this.index() < this._maxSwitches ? 'switch' : 'variable';
    };
    
    topId(): number {
        var index = this.index();
        if (index < this._maxSwitches) {
            return index * 10 + 1;
        } else {
            return (index - this._maxSwitches) * 10 + 1;
        }
    };
    refresh(): void {
        this.createContents();
        this.drawAllItems();
    };
    drawItem(index: number): void {
        var rect = this.itemRectForText(index);
        var start;
        var text;
        if (index < this._maxSwitches) {
            start = index * 10 + 1;
            text = 'S';
        } else {
            start = (index - this._maxSwitches) * 10 + 1;
            text = 'V';
        }
        var end = start + 9;
        text += ' [' + start.padZero(4) + '-' + end.padZero(4) + ']';
        this.drawText(text, rect.x, rect.y, rect.width);
    };
    isCancelTriggered(): boolean {
        return (Window_Selectable.prototype.isCancelTriggered() ||
                Input.isTriggered('debug'));
    };
    processCancel(): void {
        Window_Selectable.prototype.processCancel.call(this);
        Window_DebugRange.lastTopRow = this.topRow();
        Window_DebugRange.lastIndex = this.index();
    };
    setEditWindow(editWindow: Window_DebugEdit): void {
        this._editWindow = editWindow;
    };
    _editWindow: Window_DebugEdit;
}

//-----------------------------------------------------------------------------
// Window_DebugEdit
//
// The window for displaying switches and variables on the debug screen.

 class Window_DebugEdit extends Window_Selectable {
    constructor(x?: number, y?: number, width?: number) {
        super();
        this.initialize.apply(this, arguments);
    }
    initialize(x?: number, y?: number, width?: number): void {
        var height = this.fittingHeight(10);
        Window_Selectable.prototype.initialize.call(this, x, y, width, height);
        this._mode = 'switch';
        this._topId = 1;
        this.refresh();
    };
    _mode: string;
    _topId: number;
    maxItems(): number {
        return 10;
    };
    refresh(): void {
        this.contents.clear();
        this.drawAllItems();
    };
    drawItem(index: number): void {
        var dataId = this._topId + index;
        var idText = dataId.padZero(4) + ':';
        var idWidth = this.textWidth(idText);
        var statusWidth = this.textWidth('-00000000');
        var name = this.itemName(dataId);
        var status = this.itemStatus(dataId);
        var rect = this.itemRectForText(index);
        this.resetTextColor();
        this.drawText(idText, rect.x, rect.y, rect.width);
        rect.x += idWidth;
        rect.width -= idWidth + statusWidth;
        this.drawText(name, rect.x, rect.y, rect.width);
        this.drawText(status, rect.x + rect.width, rect.y, statusWidth, 'right');
    };
    itemName(dataId: number): string {
        if (this._mode === 'switch') {
            return $dataSystem.switches[dataId];
        } else {
            return $dataSystem.variables[dataId];
        }
    };
    itemStatus(dataId: number): void|any {
        if (this._mode === 'switch') {
            return $gameSwitches.value(dataId) ? '[ON]' : '[OFF]';
        } else {
            return String($gameVariables.value(dataId));
        }
    };
    setMode(mode: string): void {
        if (this._mode !== mode) {
            this._mode = mode;
            this.refresh();
        }
    };
    setTopId(id: number): void {
        if (this._topId !== id) {
            this._topId = id;
            this.refresh();
        }
    };
    currentId(): number {
        return this._topId + this.index();
    };
    update(): void {
        Window_Selectable.prototype.update.call(this);
        if (this.active) {
            if (this._mode === 'switch') {
                this.updateSwitch();
            } else {
                this.updateVariable();
            }
        }
    };
    updateSwitch(): void {
        if (Input.isRepeated('ok')) {
            var switchId = this.currentId();
            SoundManager.playCursor();
            $gameSwitches.setValue(switchId, !$gameSwitches.value(switchId));
            this.redrawCurrentItem();
        }
    };
    updateVariable(): void {
        var variableId = this.currentId();
        var value = $gameVariables.value(variableId);
        if (typeof value === 'number') {
            if (Input.isRepeated('right')) {
                value++;
            }
            if (Input.isRepeated('left')) {
                value--;
            }
            if (Input.isRepeated('pagedown')) {
                value += 10;
            }
            if (Input.isRepeated('pageup')) {
                value -= 10;
            }
            if ($gameVariables.value(variableId) !== value) {
                $gameVariables.setValue(variableId, value);
                SoundManager.playCursor();
                this.redrawCurrentItem();
            }
        }
    };
}
